Overlay Components
Menu
A dropdown menu triggered by a button with full keyboard navigation. Contains MenuItem, Divider, and MenuLabel subcomponents.
A dropdown menu triggered by a button with full keyboard navigation. Contains MenuItem, MenuLabel, and Divider subcomponents.
When to Use
Basic Menu
A dropdown menu triggered by a button. Pass the trigger as a React element via the trigger prop; children are the menu contents. Includes full keyboard navigation (Arrow keys, Enter, Escape, Tab) and focus management with a keyboard-visible outline on each item — focus returns to the trigger when the menu closes.
import { Menu, MenuItem, Button } from "@vaneui/ui";
<Menu trigger={<Button>Actions</Button>}> <MenuItem>Edit</MenuItem> <MenuItem>Duplicate</MenuItem> <MenuItem>Share</MenuItem></Menu>Labels & Dividers
Use MenuLabel for section headings and Divider for visual separators between groups. Divider automatically picks up the Menu's size via the menu-divider sub-theme.
<Menu trigger={<Button>Account</Button>}> <MenuLabel>Account</MenuLabel> <MenuItem>Profile</MenuItem> <MenuItem>Settings</MenuItem> <Divider /> <MenuLabel>Workspace</MenuLabel> <MenuItem>Members</MenuItem> <MenuItem>Billing</MenuItem> <Divider /> <MenuItem>Sign out</MenuItem></Menu>Items with Icons
Place SVG icons directly inside MenuItem — they are automatically flex-aligned and pointer-events-disabled so clicks pass through to the item.
import { Edit, Copy, Trash2 } from "react-feather";
<Menu trigger={<Button>File</Button>}> <MenuItem><Edit size={14} /> Edit</MenuItem> <MenuItem><Copy size={14} /> Duplicate</MenuItem> <Divider /> <MenuItem danger><Trash2 size={14} /> Delete</MenuItem></Menu>Destructive Item
Use the danger appearance prop on a MenuItem to flag a destructive action. Combine with a Divider to visually separate it from safe actions.
<Menu trigger={<Button>Manage</Button>}> <MenuItem>Rename</MenuItem> <MenuItem>Archive</MenuItem> <Divider /> <MenuItem danger>Delete permanently</MenuItem></Menu>Item Appearances
Any appearance prop works on MenuItem for semantic coloring of individual actions.
<Menu trigger={<Button>Review</Button>}> <MenuItem success>Approve</MenuItem> <MenuItem warning>Request changes</MenuItem> <MenuItem danger>Reject</MenuItem></Menu>Disabled Items
Set disabled on a MenuItem to prevent interaction. Disabled items are skipped during keyboard navigation and announced via aria-disabled.
<Menu trigger={<Button>Edit</Button>}> <MenuItem>Undo</MenuItem> <MenuItem disabled>Redo</MenuItem> <Divider /> <MenuItem>Cut</MenuItem> <MenuItem>Copy</MenuItem> <MenuItem disabled>Paste</MenuItem></Menu>Items as Links
Pass href to render a MenuItem as an anchor tag. For client-side navigation in a Next.js app, also pass tag={Link}.
<Menu trigger={<Button>Navigate</Button>}> <MenuItem href="/settings">Settings</MenuItem> <MenuItem href="/profile">Profile</MenuItem> <Divider /> <MenuItem href="https://github.com" target="_blank">GitHub</MenuItem></Menu>Menu Sizes
Set a size on Menu (e.g. <Menu lg>) and the dropdown popup, every MenuItem, MenuLabel, and nested Divider scale together automatically — no need to repeat the size on every child. Items render with larger font-size and padding, the popup frame lifts its inner padding, and dividers match. Individual children can still override with their own size prop.
<Menu lg trigger={<Button lg>Actions</Button>}> <MenuLabel>Actions</MenuLabel> <MenuItem>Edit</MenuItem> <Divider /> <MenuItem danger>Delete</MenuItem></Menu>Controlled State
Pass open and onOpenChange to drive the menu from outside state. Useful when you need to open the menu programmatically or react to its state.
const [open, setOpen] = useState(false);
<Menu open={open} onOpenChange={setOpen} trigger={<Button>Menu ({open ? "open" : "closed"})</Button>}> <MenuItem onClick={() => console.log("Edit")}>Edit</MenuItem> <MenuItem closeMenuOnClick={false}>Stay open on click</MenuItem> <MenuItem>Close on click (default)</MenuItem></Menu>Advanced Props
Menu supports additional configuration for fine-tuning behavior:
| Prop | Default | Description |
|---|---|---|
open | — | Controlled open state |
defaultOpen | false | Initial open state (uncontrolled) |
onOpenChange | — | Called when open state changes |
onClose | — | Called when the menu closes |
closeOnItemClick | true | Close menu when any item is clicked |
loop | true | Loop keyboard navigation from last to first |
disabled | false | Prevent menu from opening |
transitionDuration | 150 | Animation duration in ms |
MenuItem also accepts:
| Prop | Default | Description |
|---|---|---|
closeMenuOnClick | inherits | Override the menu-level closeOnItemClick for this item |
href | — | Render as anchor tag |
disabled | false | Prevent interaction |
focusVisible | true | Render a keyboard focus-visible outline |
noFocusVisible | — | Disable the keyboard focus-visible outline |