Components
Menu
View in FigmaDropdown menu primitives for action items, links, radio groups, separators, and submenus.
Install
npx shadcn@latest add @alix/menuPreview
Usage
<Menu>
<MenuTrigger render={<Button variant="outline">Project actions</Button>} />
<MenuContent align="start">
<MenuItem onClick={() => openBrief()}>Open brief</MenuItem>
<MenuItem onClick={() => duplicateBrief()}>Duplicate brief</MenuItem>
<MenuSeparator />
<MenuSubmenu>
<MenuSubmenuTrigger>Row density</MenuSubmenuTrigger>
<MenuContent side="inline-end" align="start" sideOffset={4}>
<MenuRadioGroup value={density} onValueChange={setDensity}>
<MenuRadioItem value="compact">Compact</MenuRadioItem>
<MenuRadioItem value="comfortable">Comfortable</MenuRadioItem>
</MenuRadioGroup>
</MenuContent>
</MenuSubmenu>
</MenuContent>
</Menu>Examples
01
Links and actions
Combine navigational items, command items, separators, and disabled options in one anchored menu.
No action yet
const [lastAction, setLastAction] = useState("No action yet");
return (
<div className="flex flex-col items-start gap-3">
<Menu>
<MenuTrigger
render={<Button variant="outline" rightIcon={<MoreHorizontal />}>Insight actions</Button>}
/>
<MenuContent align="start" className="rounded-none">
<MenuLinkItem href="/insights">
<ExternalLink className="size-4" />
Open insights hub
</MenuLinkItem>
<MenuLinkItem href="/services/transactions">
<ArrowRight className="size-4" />
View transactions services
</MenuLinkItem>
<MenuSeparator />
<MenuItem onClick={() => setLastAction("Copied link")}>
<Copy className="size-4" />
Copy link
</MenuItem>
<MenuItem disabled>Request translation</MenuItem>
</MenuContent>
</Menu>
<span className="text-xs text-muted-foreground">{lastAction}</span>
</div>
);02
Radio selection
Use a radio group inside the popup when the menu chooses one display mode rather than firing a command.
const [view, setView] = useState("leaders");
return (
<Menu>
<MenuTrigger
render={<Button variant="outline" rightIcon={<Settings2 />}>People view</Button>}
/>
<MenuContent align="start" className="rounded-none">
<MenuRadioGroup value={view} onValueChange={setView}>
<MenuRadioItem value="leaders">Leadership only</MenuRadioItem>
<MenuRadioItem value="delivery">Delivery team</MenuRadioItem>
<MenuRadioItem value="all">All contributors</MenuRadioItem>
</MenuRadioGroup>
</MenuContent>
</Menu>
);03
Toolbar overflow menu
A labelled Button can own the primary toolbar action while Menu and IconButton hold secondary report commands.
Ready
const [lastAction, setLastAction] = useState("Ready");
return (
<div className="flex flex-col items-start gap-3">
<div className="flex flex-wrap items-center gap-2">
<Button variant="outline" leftIcon={<Filter />}>Filter</Button>
<Menu>
<MenuTrigger
render={
<IconButton variant="ghost" aria-label="More report actions">
<MoreHorizontal />
</IconButton>
}
/>
<MenuContent align="end" className="rounded-none">
<MenuItem onClick={() => setLastAction("Brief duplicated")}>Duplicate brief</MenuItem>
<MenuItem onClick={() => setLastAction("Export queued")}>Export summary</MenuItem>
<MenuSeparator />
<MenuItem disabled>Archive engagement</MenuItem>
</MenuContent>
</Menu>
</div>
<span className="text-xs text-muted-foreground">{lastAction}</span>
</div>
);When to use it
Use it for
- Overflow commands, compact action lists, and mixed link/action menus anchored to one trigger.
- Single-select display settings with MenuRadioGroup when the value changes immediately.
- Submenus only when the grouping is worth the extra pointer and keyboard path.
Reach for something else
- Choosing a form value from a short flat list — use Select instead.
- Small contextual content with paragraphs or form controls — use Popover instead.
- Icon-only triggers without an accessible name — use IconButton for the trigger.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| Menu | open?, defaultOpen?, onOpenChange? | — | The Base UI state root for the menu. |
| MenuTrigger | render: ReactElement | — | Trigger slot rendered through Base UI's render prop, so a Button keeps its full API. |
| MenuContent | side?, align?, sideOffset?, alignOffset? | side "bottom", align "end", sideOffset 8 | The portalled popup surface; use side inline-end for submenu flyouts. |
| MenuItem / MenuLinkItem / MenuRadioItem | Base UI item props | — | Action, anchor, and single-select item parts with the shared item styling. |