Menu

An accessible dropdown menu for the common dropdown menu button design pattern. Menu uses roving tabIndex for focus management.

Source@chakra-ui/react

Import#

import { Menu } from '@chakra-ui/react'

Usage#

<Menu.Root>
<Menu.Trigger asChild>
<Button>
Actions
<FiChevronDown />
</Button>
</Menu.Trigger>
<Menu.Positioner>
<Menu.Content>
<Menu.Item>Download</Menu.Item>
<Menu.Item>Create a Copy</Menu.Item>
<Menu.Item>Mark as Draft</Menu.Item>
<Menu.Item>Delete</Menu.Item>
<Menu.Item>Attend a Workshop</Menu.Item>
</Menu.Conte>
</Menu.Positioner>
</Menu.Root>

Accessing the internal state#

To access the internal state of the Menu.Root, use a function as children (commonly known as a render prop). You'll get access to the internal state open and method onClose.

<Menu.Root>
{(state) => (
<>
<Menu.Trigger asChild>
<Button active={state.open}>
{state.open ? 'Close' : 'Open'} <FiChevronDown />
</Button>
</Menu.Trigger>
<Menu.Positioner>
<Menu.Content>
<Menu.Item>Download</Menu.Item>
<Menu.Item onClick={() => alert('Kagebunshin')}>
Create a Copy
</Menu.Item>
</Menu.Content>
</Menu.Positioner>
</>
)}
</Menu>

Rendering icon and command#

<Menu.Root>
<Menu.Trigger asChild aria-label='Options'>
<IconButton variant='outline'>
<FiMenu />
</IconButton>
</Menu.Trigger>
<Menu.Positioner>
<Menu.Content>
<Menu.Item>
<Menu.Icon>
<FiPlus />
</Menu.Icon>
New Tab
<Menu.Command>
<kbd>⌘T</kbd>
</Menu.Command>
</Menu.Item>
<Menu.Item>
<Menu.Icon>
<FiExternalLink />
</Menu.Icon>
New Window
<Menu.Command>
<kbd>⌘N</kbd>
</Menu.Command>
</Menu.Item>
<Menu.Item>
<Menu.Icon>
<BiShare />
</Menu.Icon>
Open File...
<Menu.Command>
<kbd>⌘O</kbd>
</Menu.Command>
</Menu.Item>
</Menu.Content>
</Menu.Positioner>
</Menu.Root>

Lazily mounting Menu.Item#

By default, the Menu.Root component renders all children of Menu.Content to the DOM, meaning that invisible menu items are still rendered but are hidden by styles.

If you want to defer rendering of each children of Menu.Content until that menu is open, you can use the isLazy prop.

This is useful to improve performance.

<Menu.Root lazyMount>
<Menu.Trigger>Open menu</Menu.Trigger>
<Menu.Positioner>
<Menu.Content>
<Menu.Item>New Window</Menu.Item>
<Menu.Item>Open Closed Tab</Menu.Item>
<Menu.Item>Open File</Menu.Item>
</Menu.Content>
</Menu.Positioner>
</Menu.Root>

Rendering menu in a portal#

To render menus in a portal, import the Portal component and wrap the Menu.Content within the Portal.

<Menu.Root>
<Menu.Trigger>Open menu</Menu.Trigger>
<Portal>
<Menu.Positioner>
<Menu.Content>
<Menu.Item>Menu 1</Menu.Item>
<Menu.Item>New Window</Menu.Item>
<Menu.Item>Open Closed Tab</Menu.Item>
<Menu.Item>Open File</Menu.Item>
</Menu.Content>
</Menu.Positioner>
</Portal>
</Menu.Root>

Grouping menu items#

To group related menu items, use the MenuGroup component and pass it a title for the group name.

<Menu.Root>
<Menu.Trigger asChild>
<Button>Profile</Button>
</Menu.Trigger>
<Menu.Positioner>
<Menu.Content>
<Menu.Group title='Profile'>
<Menu.Item>My Account</Menu.Item>
<Menu.Item>Payments </Menu.Item>
</Menu.Group>
<Menu.Separator />
<MenuGroup title='Help'>
<Menu.Item>Docs</Menu.Item>
<Menu.Item>FAQ</Menu.Item>
</MenuGroup>
</Menu.Content>
</Menu.Positioner>
</Menu.Root>

To render a Menu.Item as a link, use the attributes asChild prop

<Menu.Root>
<Menu.Trigger>Open menu</Menu.Trigger>
<Menu.Positioner>
<Menu.Content>
<Menu.Item asChild>
<a href='#'>Link 1</a>
</Menu.Item>
<Menu.Item asChild>
<a href='#'>Link 2</a>
</Menu.Item>
</Menu.Content>
</Menu.Positioner>
</Menu.Root>

You can compose a menu for table headers to help with sorting and filtering options. Use the Menu.OptionGroup and Menu.OptionItem components.

<Menu.Root closeOnSelect={false}>
<Menu.Trigger asChild>
<Button>Open Menu</Button>
</Menu.Trigger>
<Menu.Positioner>
<Menu.Content minWidth='240px'>
<Menu.OptionGroup defaultValue='asc' title='Order' type='radio'>
<Menu.OptionItem value='asc'>Ascending</Menu.OptionItem>
<Menu.OptionItem value='desc'>Descending</Menu.OptionItem>
</Menu.OptionGroup>
<Menu.Separator />
<Menu.OptionGroup title='Country' type='checkbox'>
<Menu.OptionItem value='email'>Email</Menu.OptionItem>
<Menu.OptionItem value='phone'>Phone</Menu.OptionItem>
<Menu.OptionItem value='country'>Country</Menu.OptionItem>
</Menu.OptionGroup>
</Menu.Content>
</Menu.Positioner>
</Menu.Root>

Accessibility#

Keyboard Interaction#

KeyAction
Enter or SpaceWhen Menu.Trigger receives focus, opens the menu and places focus on the first menu item.
ArrowDownWhen Menu.Trigger receives focus, opens the menu and moves focus to the first menu item.
ArrowUpWhen Menu.Trigger receives focus, opens the menu and moves focus to the last menu item.
EscapeWhen the menu is open, closes the menu and sets focus to the Menu.Trigger.
Tabno effect
HomeWhen the menu is open, moves focus to the first item.
EndWhen the menu is open, moves focus to the last item.
A-Z or a-zWhen the menu is open, moves focus to the next menu item with a label that starts with the typed character if such an menu item exists.

ARIA roles#

For Menu.Trigger:

  • role is set to button.
  • aria-haspopup is set to menu.Root.
  • When the menu is displayed, aria-expanded is set to true.
  • aria-controls is set to the id of the Menu.Content.

For Menu.Content:

  • role is set to menu.Root.
  • aria-orientation is set to vertical.

For Menu.Item:

  • role is set to menu.item.
  • Gets one of these roles menu.item/menu.itemradio/ menu.itemcheckbox.
Edit this page on GitHub

Proudly made inNigeria by Segun Adebayo

Deployed by â–² Vercel