How to build an accessible Menu in React
The trigger exposes aria-haspopup="menu" and aria-expanded, the panel is role="menu" with role="menuitem" children, focus moves to the first enabled item on open, ArrowUp/ArrowDown rove focus between items, disabled items are aria-disabled and removed from the tab order, and separators use role="separator".
When to use a Menu
- Presenting a list of actions or commands triggered from a button
- Action lists that need arrow-key navigation and Enter/Space activation
- Grouping related commands with separators behind a single trigger
When not to use it
- Selecting a persistent value from options — use Select or MultiSelect
- Right-click contextual actions on an element — use ContextMenu
- A single non-list action — use a Button
Keyboard interactions
Role menu, verified at WCAG 2.2-AA.
ArrowDownArrowUpEnterSpaceEscape
Common mistakes
Avoid: Using Menu items to pick a form value and showing the choice as selected
Prefer: Use Select for value selection; Menu items are one-shot actions
Menu items use role="menuitem" and close on activation — they are not selectable options and do not model a chosen value
Example
<Menu>
<MenuTrigger>Options</MenuTrigger>
<MenuItem onSelect={rename}>Rename</MenuItem>
<MenuItem onSelect={duplicate}>Duplicate</MenuItem>
</Menu>