Menu
A menu of actions opened from a button: roving focus, typeahead, checkbox and radio items, submenus.
WAI-ARIA patternInstallation
npx nuecrea-ui add menuUsage
import { Button } from '@/components/ui/button';
import * as Menu from '@/components/ui/menu';
export default function MenuStory() {
return (
<main className="flex gap-3">
<Menu.Root>
<Menu.Trigger render={<Button variant="outline" />}>
Edit
</Menu.Trigger>
<Menu.Portal>
<Menu.Positioner align="start">
<Menu.Popup>
<Menu.Item>Undo</Menu.Item>
<Menu.Item disabled>
Redo
</Menu.Item>
<Menu.Item>Duplicate</Menu.Item>
<Menu.Separator />
<Menu.Group>
<Menu.GroupLabel>View</Menu.GroupLabel>
<Menu.CheckboxItem defaultChecked>
<Menu.CheckboxItemIndicator />
Show grid
</Menu.CheckboxItem>
<Menu.CheckboxItem>
<Menu.CheckboxItemIndicator />
Show rulers
</Menu.CheckboxItem>
<Menu.CheckboxItem defaultChecked disabled>
<Menu.CheckboxItemIndicator />
Show guides
</Menu.CheckboxItem>
</Menu.Group>
<Menu.Separator />
<Menu.RadioGroup defaultValue="100">
<Menu.GroupLabel>Zoom</Menu.GroupLabel>
{['50', '100', '200'].map((v) => (
<Menu.RadioItem key={v} value={v}>
<Menu.RadioItemIndicator />
{v}%
</Menu.RadioItem>
))}
</Menu.RadioGroup>
<Menu.Separator />
<Menu.SubmenuRoot>
<Menu.SubmenuTrigger>Share</Menu.SubmenuTrigger>
<Menu.Portal>
<Menu.Positioner>
<Menu.Popup>
<Menu.Item>Copy link</Menu.Item>
<Menu.Item>Email</Menu.Item>
<Menu.Item>Slack</Menu.Item>
</Menu.Popup>
</Menu.Positioner>
</Menu.Portal>
</Menu.SubmenuRoot>
<Menu.Item>Delete</Menu.Item>
</Menu.Popup>
</Menu.Positioner>
</Menu.Portal>
</Menu.Root>
<Menu.Root>
<Menu.Trigger disabled render={<Button variant="outline" />}>
Locked
</Menu.Trigger>
</Menu.Root>
{/* Room to scroll the trigger out of view (data-anchor-hidden). */}
<div aria-hidden="true" className="h-[1200px] w-px" />
</main>
);
}API reference
Menu.Root
Owns open state and highlighted item. Renders nothing.
| Prop | Type | Default | Description |
|---|---|---|---|
open | boolean | — | Controlled open state. |
defaultOpen | boolean | false | Initial open state. |
loopFocus | boolean | true | Arrow keys wrap at the ends. |
highlightItemOnHover | boolean | true | Hover highlights (and focuses) items. |
disabled | boolean | false | The menu can't open. |
| Event | Payload | Description |
|---|---|---|
onOpenChange | boolean | Angular: the `open` model's change event. |
onOpenChangeComplete | boolean | After the animation finishes. |
Menu.Trigger
Opens the menu: click (focus the menu), Enter/Space/ArrowDown (first item), ArrowUp (last item). Renders <button>.
| Data attribute | Present when |
|---|---|
data-popup-open | open |
data-pressed | open after a pointer press |
data-disabled | disabled |
Menu.Portal
Moves the menu to the end of <body>. Renders <div>.
Menu.Positioner
Positions the menu; same options as Popover. Submenus default to the right, aligned to start. Renders <div> with role presentation.
| Data attribute | Present when |
|---|---|
data-open | open |
data-closed | closed / animating out |
data-anchor-hidden | trigger scrolled out of view |
data-align | always: resolved alignment |
data-side | always: resolved side |
data-instant | 'click' when opened from the keyboard |
data-nested | a submenu's positioner |
Menu.Popup
The menu (role=menu): arrow keys, Home/End, typeahead, Escape, Tab. Renders <div> with role menu.
| Data attribute | Present when |
|---|---|
data-open | open |
data-closed | closed / animating out |
data-align | always: resolved alignment |
data-instant | 'click' when opened from the keyboard |
data-side | always: resolved side |
data-starting-style | animating in |
data-ending-style | animating out |
data-nested | a submenu |
Menu.Item
An action. Closes the menu when activated (closeOnClick). Renders <div> with role menuitem.
| Prop | Type | Default | Description |
|---|---|---|---|
disabled | boolean | false | Focusable with arrows but can't be activated. |
closeOnClick | boolean | true | Close the menu on activation. |
| Data attribute | Present when |
|---|---|
data-highlighted | highlighted (keyboard or hover) |
data-disabled | disabled |
Menu.Separator
A divider. Renders <div> with role separator.
| Data attribute | Present when |
|---|---|
data-orientation | always: horizontal |
Menu.Group
Groups items; labelled by its GroupLabel. Renders <div> with role group.
Menu.GroupLabel
Labels a Group or RadioGroup. Renders <div>.
Menu.CheckboxItem
Toggles a setting; stays open (closeOnClick false). Renders <div> with role menuitemcheckbox.
| Prop | Type | Default | Description |
|---|---|---|---|
checked | boolean | — | Controlled. |
defaultChecked | boolean | false | Initial. |
disabled | boolean | false | Can't be toggled. |
closeOnClick | boolean | false | Close on toggle. |
| Event | Payload | Description |
|---|---|---|
onCheckedChange | boolean | Angular: the `checked` model's change event. |
| Data attribute | Present when |
|---|---|
data-checked | checked |
data-unchecked | not checked |
data-highlighted | highlighted (keyboard or hover) |
data-disabled | disabled |
Menu.CheckboxItemIndicator
Shown while checked (styled: a check icon). Renders <span>.
| Prop | Type | Default | Description |
|---|---|---|---|
keepMounted | boolean | false | Keep while unchecked. |
| Data attribute | Present when |
|---|---|
data-checked | checked |
data-unchecked | not checked |
data-disabled | disabled |
data-highlighted | highlighted (keyboard or hover) |
data-starting-style | animating in |
data-ending-style | animating out |
Menu.RadioGroup
Holds the selected value of its radio items. Renders <div> with role group.
| Prop | Type | Default | Description |
|---|---|---|---|
value | unknown | — | Controlled. |
defaultValue | unknown | — | Initial. |
disabled | boolean | false | Disable all items. |
| Event | Payload | Description |
|---|---|---|
onValueChange | unknown | Angular: the `value` model's change event. |
Menu.RadioItem
Selects its value in the group; stays open. Renders <div> with role menuitemradio.
| Prop | Type | Default | Description |
|---|---|---|---|
value | unknown | — | Required. |
disabled | boolean | false | Can't be selected. |
closeOnClick | boolean | false | Close on select. |
| Data attribute | Present when |
|---|---|
data-checked | checked |
data-unchecked | not checked |
data-highlighted | highlighted (keyboard or hover) |
Menu.RadioItemIndicator
Shown while selected (styled: a dot). Renders <span>.
| Prop | Type | Default | Description |
|---|---|---|---|
keepMounted | boolean | false | Keep while unselected. |
| Data attribute | Present when |
|---|---|
data-checked | checked |
data-unchecked | not checked |
data-highlighted | highlighted (keyboard or hover) |
data-starting-style | animating in |
data-ending-style | animating out |
Keyboard
| Key | Action |
|---|---|
| Enter / Space / ArrowDown | On the trigger: open with the first item focused. |
| ArrowUp | On the trigger: open with the last item focused. |
| ArrowDown / ArrowUp | Move between items (disabled included), wrapping. |
| Home / End | First / last item. |
| Letters | Typeahead: jump to the next item starting with the typed text. |
| Enter / Space | Activate the item. |
| ArrowRight / ArrowLeft | Open / close a submenu. |
| Escape | Close (a submenu closes only itself). |
| Tab | Close the menu; focus returns to the trigger. |