Menu
Menu is a component that displays a common dropdown menu.
<Menu.Root>
<Menu.Trigger>
<Button>Menu</Button>
</Menu.Trigger>
<Menu.Content>
<Menu.Item value="naruto">うずまきナルト</Menu.Item>
<Menu.Item value="sasuke">うちはサスケ</Menu.Item>
<Menu.Item value="sakura">春野サクラ</Menu.Item>
</Menu.Content>
</Menu.Root>
Usage
import { Menu } from "@yamada-ui/react"
import { Menu } from "@/components/ui"
import { Menu } from "@workspaces/ui"
<Menu.Root>
<Menu.Trigger />
<Menu.ContextTrigger />
<Menu.Anchor />
<Menu.Content>
<Menu.Header />
<Menu.Group>
<Menu.Item>
<Menu.Label />
<Menu.Indicator />
<Menu.Command />
</Menu.Item>
</Menu.Group>
<Menu.Separator />
<Menu.OptionGroup>
<Menu.OptionItem />
</Menu.OptionGroup>
<Menu.Footer />
</Menu.Content>
</Menu.Root>
Use Items
const items = useMemo<Menu.Item[]>(
() => [
{ label: "うずまきナルト", value: "naruto" },
{ label: "うちはサスケ", value: "sasuke" },
{ label: "春野サクラ", value: "sakura" },
],
[],
)
return (
<Menu.Root>
<Menu.Trigger>
<Button>Menu</Button>
</Menu.Trigger>
<Menu.Content items={items} />
</Menu.Root>
)
Change Size
const items = useMemo<Menu.Item[]>(
() => [
{ label: "うずまきナルト", value: "naruto" },
{ label: "うちはサスケ", value: "sasuke" },
{ label: "春野サクラ", value: "sakura" },
],
[],
)
return (
<HStack>
<For each={["sm", "md", "lg"]}>
{(size) => (
<Menu.Root key={size} size={size}>
<Menu.Trigger>
<Button>{toTitleCase(size)}</Button>
</Menu.Trigger>
<Menu.Content items={items} />
</Menu.Root>
)}
</For>
</HStack>
)
Handle Selection Event
To handle selection event, use onSelect.
const items = useMemo<Menu.Item[]>(
() => [
{ label: "うずまきナルト", value: "naruto" },
{ label: "うちはサスケ", value: "sasuke" },
{ label: "春野サクラ", value: "sakura" },
],
[],
)
return (
<Menu.Root onSelect={(value) => console.log("selected", value)}>
<Menu.Trigger>
<Button>Menu</Button>
</Menu.Trigger>
<Menu.Content items={items} />
</Menu.Root>
)
Add Dividers
const items = useMemo<Menu.Item[]>(
() => [
{ label: "うずまきナルト", value: "naruto" },
{ label: "うちはサスケ", value: "sasuke" },
{ label: "春野サクラ", value: "sakura" },
{ type: "separator" },
{ label: "大蛇丸", value: "orochimaru" },
{ label: "自來也", value: "pervy-sage" },
{ label: "綱手", value: "tsunade" },
],
[],
)
return (
<HStack>
<Menu.Root>
<Menu.Trigger>
<Button>Menu with items</Button>
</Menu.Trigger>
<Menu.Content items={items} />
</Menu.Root>
<Menu.Root>
<Menu.Trigger>
<Button>Menu with composition</Button>
</Menu.Trigger>
<Menu.Content>
<Menu.Item value="naruto">うずまきナルト</Menu.Item>
<Menu.Item value="sasuke">うちはサスケ</Menu.Item>
<Menu.Item value="sakura">春野サクラ</Menu.Item>
<Menu.Separator />
<Menu.Item value="orochimaru">大蛇丸</Menu.Item>
<Menu.Item value="pervy-sage">自來也</Menu.Item>
<Menu.Item value="tsunade">綱手</Menu.Item>
</Menu.Content>
</Menu.Root>
</HStack>
)
Grouping
const items = useMemo<Menu.Item[]>(
() => [
{
items: [
{ label: "うずまきナルト", value: "naruto" },
{ label: "うちはサスケ", value: "sasuke" },
{ label: "春野サクラ", value: "sakura" },
],
label: "第七班",
},
{
items: [
{ label: "大蛇丸", value: "orochimaru" },
{ label: "自來也", value: "pervy-sage" },
{ label: "綱手", value: "tsunade" },
],
label: "伝説の三忍",
},
],
[],
)
return (
<HStack>
<Menu.Root>
<Menu.Trigger>
<Button>Menu with items</Button>
</Menu.Trigger>
<Menu.Content items={items} />
</Menu.Root>
<Menu.Root>
<Menu.Trigger>
<Button>Menu with composition</Button>
</Menu.Trigger>
<Menu.Content>
<Menu.Group label="第七班">
<Menu.Item value="naruto">うずまきナルト</Menu.Item>
<Menu.Item value="sasuke">うちはサスケ</Menu.Item>
<Menu.Item value="sakura">春野サクラ</Menu.Item>
</Menu.Group>
<Menu.Separator />
<Menu.Group label="伝説の三忍">
<Menu.Item value="orochimaru">大蛇丸</Menu.Item>
<Menu.Item value="pervy-sage">自來也</Menu.Item>
<Menu.Item value="tsunade">綱手</Menu.Item>
</Menu.Group>
</Menu.Content>
</Menu.Root>
</HStack>
)
Display Icons
const items = useMemo<Menu.Item[]>(
() => [
{
label: (
<>
<Menu.Indicator>
<PlusIcon />
</Menu.Indicator>
New Tab
</>
),
value: "tab",
},
{
label: (
<>
<Menu.Indicator>
<SquareArrowOutUpRightIcon />
</Menu.Indicator>
New Window
</>
),
value: "window",
},
{
label: (
<>
<Menu.Indicator>
<SquarePenIcon />
</Menu.Indicator>
New File
</>
),
value: "file",
},
],
[],
)
return (
<HStack>
<Menu.Root>
<Menu.Trigger>
<Button>Menu with items</Button>
</Menu.Trigger>
<Menu.Content items={items} />
</Menu.Root>
<Menu.Root>
<Menu.Trigger>
<Button>Menu with composition</Button>
</Menu.Trigger>
<Menu.Content>
<Menu.Item value="tab">
<Menu.Indicator>
<PlusIcon />
</Menu.Indicator>
New Tab
</Menu.Item>
<Menu.Item value="window">
<Menu.Indicator>
<SquareArrowOutUpRightIcon />
</Menu.Indicator>
New Window
</Menu.Item>
<Menu.Item value="file">
<Menu.Indicator>
<SquarePenIcon />
</Menu.Indicator>
New File
</Menu.Item>
</Menu.Content>
</Menu.Root>
</HStack>
)
Display Commands
const items = useMemo<Menu.Item[]>(
() => [
{
label: (
<>
New Tab
<Menu.Command>⌘T</Menu.Command>
</>
),
value: "tab",
},
{
label: (
<>
New Window
<Menu.Command>⌘N</Menu.Command>
</>
),
value: "window",
},
{
label: (
<>
Open File
<Menu.Command>⌘O</Menu.Command>
</>
),
value: "file",
},
],
[],
)
return (
<HStack>
<Menu.Root>
<Menu.Trigger>
<Button>Menu with items</Button>
</Menu.Trigger>
<Menu.Content items={items} />
</Menu.Root>
<Menu.Root>
<Menu.Trigger>
<Button>Menu with composition</Button>
</Menu.Trigger>
<Menu.Content>
<Menu.Item value="tab">
New Tab
<Menu.Command>⌘T</Menu.Command>
</Menu.Item>
<Menu.Item value="window">
New Window
<Menu.Command>⌘N</Menu.Command>
</Menu.Item>
<Menu.Item value="file">
Open File
<Menu.Command>⌘O</Menu.Command>
</Menu.Item>
</Menu.Content>
</Menu.Root>
</HStack>
)
Set Selectable Items
const [value, setValue] = useState<string[]>(["naruto"])
const items = useMemo<Menu.Item[]>(
() => [
{
type: "checkbox",
items: [
{ label: "うずまきナルト", value: "naruto" },
{ label: "うちはサスケ", value: "sasuke" },
{ label: "春野サクラ", value: "sakura" },
{ label: "はたけカカシ", value: "kakashi", disabled: true },
],
value,
onChange: setValue,
},
],
[value],
)
return (
<HStack>
<Menu.Root>
<Menu.Trigger>
<Button>Menu with items</Button>
</Menu.Trigger>
<Menu.Content items={items} />
</Menu.Root>
<Menu.Root>
<Menu.Trigger>
<Button>Menu with composition</Button>
</Menu.Trigger>
<Menu.Content>
<Menu.OptionGroup type="checkbox" value={value} onChange={setValue}>
<Menu.OptionItem value="naruto">うずまきナルト</Menu.OptionItem>
<Menu.OptionItem value="sasuke">うちはサスケ</Menu.OptionItem>
<Menu.OptionItem value="sakura">春野サクラ</Menu.OptionItem>
<Menu.OptionItem disabled value="kakashi">
はたけカカシ
</Menu.OptionItem>
</Menu.OptionGroup>
</Menu.Content>
</Menu.Root>
</HStack>
)
Nested Menu
<Menu.Root>
<Menu.Trigger>
<Button>Menu</Button>
</Menu.Trigger>
<Menu.Content>
<Menu.Item value="naruto">うずまきナルト</Menu.Item>
<Menu.Item value="sasuke">うちはサスケ</Menu.Item>
<Menu.Item value="sakura">春野サクラ</Menu.Item>
<Menu.Root>
<Menu.Trigger>
<Menu.Item>Settings</Menu.Item>
</Menu.Trigger>
<Menu.Content>
<Menu.Item value="extensions">Extensions</Menu.Item>
<Menu.Item value="theme">Theme</Menu.Item>
<Menu.Item value="tasks">User Tasks</Menu.Item>
</Menu.Content>
</Menu.Root>
</Menu.Content>
</Menu.Root>
Use Context Menu
<Menu.Root>
<Menu.ContextTrigger>
<Center
borderStyle="dashed"
borderWidth="1px"
h="xs"
p="md"
rounded="l2"
w="full"
>
<Text>Right Click Here</Text>
</Center>
</Menu.ContextTrigger>
<Menu.Content>
<Menu.Item value="copy">Copy</Menu.Item>
<Menu.Item value="paste">Paste</Menu.Item>
<Menu.Item value="delete">Delete</Menu.Item>
</Menu.Content>
</Menu.Root>
Display Menu on Different Element
const items = useMemo<Menu.Item[]>(
() => [
{ label: "うずまきナルト", value: "naruto" },
{ label: "うちはサスケ", value: "sasuke" },
{ label: "春野サクラ", value: "sakura" },
],
[],
)
return (
<Menu.Root>
<HStack>
<Menu.Anchor>
<Center borderWidth="1px" h="10" px="3" rounded="l2">
Here display Popover
</Center>
</Menu.Anchor>
<Menu.Trigger>
<Button>Menu</Button>
</Menu.Trigger>
</HStack>
<Menu.Content items={items} />
</Menu.Root>
)
Disable Close on Select
To disable the close on select, set closeOnSelect to false.
const items = useMemo<Menu.Item[]>(
() => [
{ label: "うずまきナルト", value: "naruto" },
{ label: "うちはサスケ", value: "sasuke" },
{ label: "春野サクラ", value: "sakura" },
],
[],
)
return (
<Menu.Root closeOnSelect={false}>
<Menu.Trigger>
<Button>Menu</Button>
</Menu.Trigger>
<Menu.Content items={items} />
</Menu.Root>
)
Set Initial Focus
To set initial focus, pass a Ref to initialFocusRef.
const ref = useRef<HTMLDivElement>(null)
return (
<Menu.Root initialFocusRef={ref}>
<Menu.Trigger>
<Button>Menu</Button>
</Menu.Trigger>
<Menu.Content>
<Menu.Item value="status">Set Status</Menu.Item>
<Menu.Item ref={ref} value="profile">
Edit Profile
</Menu.Item>
<Menu.Item value="preferences">Preferences</Menu.Item>
</Menu.Content>
</Menu.Root>
)
"use client" to the top of the file.Change Placement
To change the display position, set placement to "start", "end-end", etc. By default, "end-start" is set.
const items = useMemo<Menu.Item[]>(
() => [
{ label: "うずまきナルト", value: "naruto" },
{ label: "うちはサスケ", value: "sasuke" },
{ label: "春野サクラ", value: "sakura" },
],
[],
)
return (
<Wrap gap="md">
<For
each={[
"start",
"start-start",
"start-end",
"end",
"end-start",
"end-end",
"center-start",
"center-start-start",
"center-start-end",
"center-end",
"center-end-start",
"center-end-end",
]}
>
{(placement) => (
<Menu.Root key={placement} placement={placement}>
<Menu.Trigger>
<Button>{toTitleCase(placement)}</Button>
</Menu.Trigger>
<Menu.Content items={items} />
</Menu.Root>
)}
</For>
</Wrap>
)
Change Animation
To change the animation, set animationScheme to "inline-start", "block-end", etc. By default, "scale" is set.
const items = useMemo<Menu.Item[]>(
() => [
{ label: "うずまきナルト", value: "naruto" },
{ label: "うちはサスケ", value: "sasuke" },
{ label: "春野サクラ", value: "sakura" },
],
[],
)
return (
<Wrap gap="md">
<For
each={["scale", "block-end", "block-start", "inline-start", "inline-end"]}
>
{(animationScheme) => (
<Menu.Root key={animationScheme} animationScheme={animationScheme}>
<Menu.Trigger>
<Button>{toTitleCase(animationScheme)}</Button>
</Menu.Trigger>
<Menu.Content items={items} />
</Menu.Root>
)}
</For>
</Wrap>
)
Change Offset
To change the offset, set a value to gutter or offset.
const items = useMemo<Menu.Item[]>(
() => [
{ label: "うずまきナルト", value: "naruto" },
{ label: "うちはサスケ", value: "sasuke" },
{ label: "春野サクラ", value: "sakura" },
],
[],
)
return (
<HStack>
<Menu.Root gutter={32}>
<Menu.Trigger>
<Button>Menu</Button>
</Menu.Trigger>
<Menu.Content items={items} />
</Menu.Root>
<Menu.Root offset={[16, 16]}>
<Menu.Trigger>
<Button>Menu</Button>
</Menu.Trigger>
<Menu.Content items={items} />
</Menu.Root>
</HStack>
)
Change Duration
To change the duration, set a numerical value (seconds) to duration.
const items = useMemo<Menu.Item[]>(
() => [
{ label: "うずまきナルト", value: "naruto" },
{ label: "うちはサスケ", value: "sasuke" },
{ label: "春野サクラ", value: "sakura" },
],
[],
)
return (
<Menu.Root duration={0.4}>
<Menu.Trigger>
<Button>Menu</Button>
</Menu.Trigger>
<Menu.Content items={items} />
</Menu.Root>
)
Access Internal State
To access internal state, pass a function to the children of Menu.Root.
const items = useMemo<Menu.Item[]>(
() => [
{ label: "うずまきナルト", value: "naruto" },
{ label: "うちはサスケ", value: "sasuke" },
{ label: "春野サクラ", value: "sakura" },
],
[],
)
return (
<Menu.Root>
{({ open }) => (
<>
<Menu.Trigger>
<Button>{open ? "Close" : "Open"} Menu</Button>
</Menu.Trigger>
<Menu.Content items={items} />
</>
)}
</Menu.Root>
)
"use client" to the top of the file.Disable Close on Outside Click
To disable closing when clicking outside, set closeOnBlur to false.
const items = useMemo<Menu.Item[]>(
() => [
{ label: "うずまきナルト", value: "naruto" },
{ label: "うちはサスケ", value: "sasuke" },
{ label: "春野サクラ", value: "sakura" },
],
[],
)
return (
<Menu.Root closeOnBlur={false}>
<Menu.Trigger>
<Button>Menu</Button>
</Menu.Trigger>
<Menu.Content items={items} />
</Menu.Root>
)
Disabling Items
To disable items, set disabled to true.
const items = useMemo<Menu.Item[]>(
() => [
{ label: "うずまきナルト", value: "naruto" },
{ label: "うちはサスケ", value: "sasuke", disabled: true },
{ label: "春野サクラ", value: "sakura" },
],
[],
)
return (
<Menu.Root>
<Menu.Trigger>
<Button>Menu</Button>
</Menu.Trigger>
<Menu.Content items={items} />
</Menu.Root>
)
Add Header or Footer
To add header or footer, set ReactNode to header or footer of Menu.Content.
const items = useMemo<Menu.Item[]>(
() => [
{ label: "うずまきナルト", value: "naruto" },
{ label: "うちはサスケ", value: "sasuke" },
{ label: "春野サクラ", value: "sakura" },
{ label: "大蛇丸", value: "orochimaru" },
{ label: "自來也", value: "pervy-sage" },
{ label: "綱手", value: "tsunade" },
],
[],
)
return (
<Menu.Root>
<Menu.Trigger>
<Button>Menu</Button>
</Menu.Trigger>
<Menu.Content
header="キャラクター"
footer="キャラクター"
items={items}
maxH="2xs"
/>
</Menu.Root>
)
Control
const { open, onOpen, onClose } = useDisclosure()
const items = useMemo<Menu.Item[]>(
() => [
{ label: "うずまきナルト", value: "naruto" },
{ label: "うちはサスケ", value: "sasuke" },
{ label: "春野サクラ", value: "sakura" },
],
[],
)
return (
<Menu.Root open={open} onOpen={onOpen} onClose={onClose}>
<Menu.Trigger>
<Button>Menu</Button>
</Menu.Trigger>
<Menu.Content items={items} />
</Menu.Root>
)
"use client" to the top of the file.Props
Accessibility
The Menu follows the WAI-ARIA - Menu and Menubar Pattern and WAI-ARIA - Menu Button Pattern for accessibility.
Keyboard Navigation
| Key | Description | State |
|---|---|---|
Space, Enter | Opens the menu and focuses the first enabled item. | - |
| Activates the focused item and closes all menus if already within the menu. | closeOnSelect={true} | |
ArrowRight | If the focused item is a submenu trigger, opens the submenu and focuses the first enabled item. | subMenuDirection="end" |
| Closes the submenu and focuses the submenu trigger if already within a submenu. | subMenuDirection="start" | |
ArrowLeft | If the focused item is a submenu trigger, opens the submenu and focuses the first enabled item. | subMenuDirection="start" |
| Closes the submenu and focuses the submenu trigger if already within a submenu. | subMenuDirection="end" | |
ArrowUp | Opens the menu and focuses the last enabled item. Focuses the previous enabled item if already within the menu. If on the first item, focuses the last. | - |
ArrowDown | Opens the menu and focuses the first enabled item. Focuses the next enabled item if already within the menu. If on the last item, focuses the first. | - |
Home | Focuses the first enabled item if already within the menu. | - |
End | Focuses the last enabled item if already within the menu. | - |
Escape | Closes the menu and focuses the trigger. | closeOnEsc={true} |
ARIA Roles and Attributes
| Element | Roles and Attributes | Usage |
|---|---|---|
button.ui-menu__trigger | role="button" | Indicates that it is a button. |
aria-controls | Set to the related div.ui-menu__content id when the menu is open, undefined when closed. | |
aria-disabled | Set to "true" when disabled is set. | |
aria-expanded | Set to "true" when the menu is open, "false" when closed. | |
aria-haspopup="menu" | Indicates that a menu exists. | |
div.ui-menu__context-trigger | role="application" | Indicates that it is an application. |
aria-controls | Set to the related div.ui-menu__content id when the menu is open, undefined when closed. | |
aria-disabled | Set to "true" when disabled is set. | |
aria-expanded | Set to "true" when the menu is open, "false" when closed. | |
aria-haspopup="menu" | Indicates that a menu exists. | |
div.ui-menu__content | role="menu" | Indicates that it is a menu. |
aria-activedescendant | Set to the id of the focused item. | |
aria-hidden | Set to "false" when the menu is open, "true" when closed. | |
aria-labelledby | Set to the id of the related button.ui-menu__trigger or div.ui-menu__context-trigger. | |
span.ui-menu__label | role="presentation" | Indicates that it is for presentation. |
div.ui-menu__group | role="group" | Indicates that it is a group. |
aria-labelledby | Set to the id of the related span.ui-menu__label. | |
div.ui-menu__item | role="menuitem" | Indicates that it is a menu item. |
aria-disabled | Set to "true" when disabled is set. | |
div.ui-menu__item--option | role | Set to "menuitemradio" when Menu.OptionGroup type is "radio", set to "menuitemcheckbox" when type is "checkbox". |
hr.ui-menu__separator | role="separator" | Indicates that it is a separator. |
Similar Components
Select
Select is a component used for allowing a user to choose values from a list of options.
Autocomplete
Autocomplete is a component used to display suggestions in response to user text input.
NativePopover
NativePopover is a component that floats around an element to display information using the HTML Popover API.
ActionBar
ActionBar is a component that is used to display a bottom action bar with a set of actions.
Popover
Popover is a component that floats around an element to display information.
Tooltip
Tooltip is a component that displays short information, such as supplementary details for an element.
Drawer
Drawer is a component for a panel that appears from the edge of the screen.
Modal
Modal is a component that is displayed over the main content to focus the user's attention solely on the information.
Uses Components & Hooks
Popover
Popover is a component that floats around an element to display information.
Button
Button is an interactive component that allows users to perform actions such as submitting forms and toggling modals.
Icon
Icon is a general icon component that can be used in your projects.
useDescendants
useDescendants is a custom hook that manages descendants.
useDisclosure
useDisclosure is a custom hook that helps handle common open/close or toggle scenarios. It can be used to control components such as Modal, Dialog, Drawer, etc.