Menu
Accessible dropdown action menus following the WAI-ARIA Menu Button pattern, featuring roving focus keyboard navigation, shortcut keys, danger states, and focus return.
Basic Action Menu
With Icons & Shortcuts
Grouped Menu Sections
API reference
MenuProps
triggerReact.ReactNode—
Name: trigger
Description: The trigger element (e.g. <Button>). Automatically wired with accessibility attributes.
Type: React.ReactNode
Default: —
childrenReact.ReactNode—
Name: children
Description: Menu content containing MenuItem, MenuDivider, and MenuGroup.
Type: React.ReactNode
Default: —
labelstring—
Name: label
Description: Accessible label for the menu if trigger does not contain visible text.
Type: string
Default: —
isOpenboolean—
Name: isOpen
Description: Controlled open state.
Type: boolean
Default: —
defaultOpenbooleanfalse
Name: defaultOpen
Description: Initial open state when uncontrolled.
Type: boolean
Default: false
onOpenChange(isOpen: boolean) => void—
Name: onOpenChange
Description: Callback fired when open state changes.
Type: (isOpen: boolean) => void
Default: —
placement'bottom-start' | 'bottom-end' | 'top-start' | 'top-end''bottom-start'
Name: placement
Description: Alignment of dropdown menu relative to the trigger.
Type: 'bottom-start' | 'bottom-end' | 'top-start' | 'top-end'
Default: 'bottom-start'
closeOnSelectbooleantrue
Name: closeOnSelect
Description: Whether selecting a menu item automatically closes the menu.
Type: boolean
Default: true
MenuItemProps
childrenReact.ReactNode—
Name: children
Description: Item label text or elements.
Type: React.ReactNode
Default: —
onClick(event: React.MouseEvent | React.KeyboardEvent) => void—
Name: onClick
Description: Action handler invoked on click, Enter, or Space.
Type: (event: React.MouseEvent | React.KeyboardEvent) => void
Default: —
hrefstring—
Name: href
Description: Optional destination URL to render as an accessible navigation link.
Type: string
Default: —
iconReact.ReactNode—
Name: icon
Description: Optional leading icon or SVG element.
Type: React.ReactNode
Default: —
shortcutstring—
Name: shortcut
Description: Optional keyboard shortcut label (e.g. ⌘S).
Type: string
Default: —
disabledbooleanfalse
Name: disabled
Description: Disables interaction and skips the item during keyboard navigation.
Type: boolean
Default: false
dangerbooleanfalse
Name: danger
Description: Applies destructive danger styling for critical actions (e.g. Delete).
Type: boolean
Default: false
MenuGroupProps
labelstring—
Name: label
Description: Optional section header text associated via aria-labelledby.
Type: string
Default: —
childrenReact.ReactNode—
Name: children
Description: Group content items.
Type: React.ReactNode
Default: —
Keyboard Navigation (WAI-ARIA Menu Button)
| Key | Focus Target | Behavior |
|---|---|---|
| Enter / Space / ↓ | Trigger Button | Opens menu and moves focus to the first non-disabled item. |
| ↑ | Trigger Button | Opens menu and moves focus to the last non-disabled item. |
| ↓ | Menu Item | Moves focus to the next item, skipping disabled items and wrapping around. |
| ↑ | Menu Item | Moves focus to the previous item, skipping disabled items and wrapping around. |
| Home | Menu Item | Jumps focus to the first non-disabled item. |
| End | Menu Item | Jumps focus to the last non-disabled item. |
| Escape | Menu Item | Closes menu and immediately returns focus to the trigger button. |
| Tab | Menu Item | Closes menu and allows normal tab order progression. |
Accessibility Highlights
- Trigger Semantics: Configured with
aria-haspopup="menu"andaria-expanded. - Roving Tabindex: Only the active item receives focus during arrow key navigation; pressing Tab doesn't trap keyboard focus inside the menu.
- Focus Return (WCAG 2.4.3): Dismissing via Escape or activating an action item returns focus directly to the trigger button.
- Semantic Groups & Dividers: Uses
role="group"with accessible section headers androle="separator"for dividing lines. - Zero 3rd-Party Dependencies: Native React and CSS implementation with zero external runtime footprint.