Menu
A list of actions that opens from a button. Use it to tuck away secondary actions on a row, a card or a toolbar, not to navigate or to pick a value.
Installation
Set up Camaleo once (Installation), then import the parts you need. The popup renders in a portal and keeps the skin, mode and brand of the page around it.
import { Menu, MenuTrigger, MenuContent, MenuItem, MenuCheckboxItem, MenuRadioGroup, MenuRadioItem, MenuSub, MenuSubTrigger, MenuSubContent, MenuGroup, MenuGroupLabel, MenuSeparator } from "@camaleo/react";Anatomy
Menu holds the open state. MenuTrigger is the button (data-slot="menu-trigger", or the Button's own slot when you pass render={<Button />}); MenuContent renders the popup below in a portal. Every part has a data-slot you can target from CSS.
Examples
Every example is a real file you can copy. They all wear the skin, mode and brand from the bar above, and they all start closed.
With shortcuts
Show the shortcut with Kbd so people learn it while they use the menu, and add aria-keyshortcuts so screen readers say it too. The menu only displays it: wire the keys yourself.
Groups and separators
Past five or six items, a MenuGroupLabel over each group lets people skip to the right part instead of reading every row.
Checkbox items
Turn options on and off. MenuCheckboxItem stays open after a click and reports aria-checked, so screen readers say "checked" or "not checked".
Act, then announce
Pick an action. Focus goes back to the trigger, and a role="status" line tells screen readers what happened, because the menu that showed it is gone.
Destructive, with a confirm
Pick "Delete project". It comes last, after a separator, and opens an AlertDialog; finalFocus brings focus back to the menu button when it closes.
Disabled, with a reason
Keep an unavailable action in the menu so people learn it exists, and say why in the item itself: the reason is read with its name.
Icon-only trigger
A "⋯" button has no text, so its aria-label says what the actions are for: "Actions for invoice INV-4029", not just "More".
Links as items
For a few related pages, like a help menu, give an item render={<a href="…" />}: it opens with Enter, and the browser can open it in a new tab.
Radio items and a submenu
For a view setting with one choice, like list or grid, use MenuRadioItem; tuck a longer group, like the sort order, into a MenuSub that → opens and ← closes.
In context
Menus keep the secondary actions out of the way. These are whole pieces of UI you can copy, in the skin you picked.
| Invoice | Client | Status | Amount | |
|---|---|---|---|---|
| INV-4029 | Northwind Traders | Paid | $4,250.00 | |
| INV-4028 | Blue Harbor Café | Pending | $1,180.50 | |
| INV-4027 | Lumen Studio | Pending | $12,900.00 |
Office lease 2027.pdf
2.4 MB · Edited Oct 14, 2026
Guidelines
"Rename", "Duplicate", "Move to folder…": people know what each item does before they pick it.
After the click the trigger still says "Country", and the form gets nothing. Use a Select; to move between pages, use links or a NavigationMenu.
The red item is out of the way of a quick ↓ Enter, and its color says it is different.
One slip of the pointer or the arrow keys and the wrong thing is gone.
Props
danger colors a destructive action. Put it last, after a separator.<a> for a link.These are the props of MenuItem. Menu takes Base UI's root props: open, onOpenChange, modal and disabled. MenuCheckboxItem takes checked, defaultChecked, onCheckedChange and closeOnClick (off by default). MenuRadioGroup takes value, defaultValue and onValueChange, and each MenuRadioItem a value; a MenuGroupLabel inside the group names it. Wrap a MenuSubTrigger and its MenuSubContent in a MenuSub. MenuTrigger takes render, usually <Button /> or <IconButton aria-label="…" />.
Styling hooks
Restyle it without forking: target the attributes, or set the tokens on a parent, a skin or the popup itself.
Attributes
Tokens it reads
Color
Shape & size
Type & motion
This component only
Accessibility
- The trigger reports aria-haspopup and aria-expanded, and so does a submenu trigger; items are menuitem, checkbox items menuitemcheckbox and radio items menuitemradio, both with aria-checked.
- Disabled items stay in the arrow-key order and are announced as unavailable, so a reason in their text is read too.
- After an action, the menu is gone: announce the result with role="status" and keep focus on the trigger.
- The popup is portalled but keeps the skin through PortalScope, and contrast passes WCAG 2.2 AA in all 13 skins.