-
Hello there 👋 At Doist we have a menu that looks like this: Most of this menu is built with the const state = Ariakit.useCompositeState({
focusLoop: true,
orientation: 'horizontal',
})
return (
<Ariakit.Group>
<Ariakit.GroupLabel>Due date</Ariakit.GroupLabel>
<Ariakit.Composite role="menubar" state={state}>
<Ariakit.CompositeItem>Green calendar</Ariakit.CompositeItem>
<Ariakit.CompositeItem>Yellow sun</Ariakit.CompositeItem>
<Ariakit.CompositeItem>Blue sofa</Ariakit.CompositeItem>
<Ariakit.CompositeItem>Purple arrow</Ariakit.CompositeItem>
<Ariakit.CompositeItem>Blue arrow</Ariakit.CompositeItem>
</Ariakit.Composite>
</Ariakit.Group>
) Note There's a lot more to it, of course, specific to our use case and internal components, but that's the gist of the component composition for the custom "Due date" and "Priority" groups. Everything is working great, but implementing keyboard navigating with the up/down/left/right arrow keys was tricky to implement because it required focus to be set programmatically in multiple use cases:
On top of this, we also have custom vertical navigation between the "Due date" and "Priority" groups so that, for instance, if the "blue sofa" icon was focused in the "Due date" group, pressing As you can imagine, the implementation to have all this working is becoming a little bit complex, especially since we have to replicate this behaviour throughout multiple use cases, which don't necessarily render the same items all the time, so we have a lot of logic to account for that dynamic behaviour. What I'm looking for is to find out if it's possible to refactor our "Due date" and "Priority" custom components in a way that would make keyboard navigation, both vertically between these custom components and the surrounding menu items, and horizontally within each custom component, more painless and easy to maintain. In other words, is it possible to replicate what we have from built-in functionality in Ariakit, deferring all keyboard handling to Ariakit? Happy holidays 🎆 |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 2 replies
-
Hi @rfgamaral! I'd really recommend using the default keyboard interactions for menus. In other words, allow users to use the up and down arrow keys to navigate through menu items, even if they're placed horizontally within a vertical menu. This approach is already standard practice in system menus like those found on browser toolbars. The "zoom" controls may be arranged horizontally, but you still use vertical arrow keys to navigate them. This is the most reliable method to handle this type of menu. If you also want to allow the use of horizontal arrow keys, you can set That said, if you're still interested in pursuing this route, it's important to note that As an alternative, you can transform the entire menu into a This interaction model aligns most closely with what you've described. However, a grid can be more verbose and complex for screen reader users to navigate since it involves both rows and columns. Additionally, general support for this role isn't as robust as it is for the menu widget. Here's an example: https://stackblitz.com/edit/nwfdpj?file=menu%2Fstyle.css,menu%2Findex.tsx&theme=dark Should you decide to follow this path, I recommend testing the solution with real users, including those who use screen readers. |
Beta Was this translation helpful? Give feedback.
-
Hey @diegohaz, thank you for quickly getting back to me, but I was OOO during the last week, and only know I'm able to look at this and reply you back.
Interesting, didn't know that. Will reach out to our UI/UX team about this, so we can come up with a decision.
If we decide to only keep vertical arrow key navigation (as you suggested above), can we achieve the UI presented above without a grid? I'm struggling to understand how exactly to implement that menu. Could you be so kind and provide another code example? Would really appreciate that. |
Beta Was this translation helpful? Give feedback.
In that case, you don't need anything fancy. Simply use
Menu
,MenuGroup
, andMenuItem
and style them appropriately. Essentially, you just apply CSS to display these items horizontally. Something like this: