Menu
Offer a compact list of actions and choices.
Installation
pnpm dlx shadcn@4.18.0 add @siteplane/menuComplete the one-time setup first. Registry JSON lists source files and dependencies.
For this page’s examples, also install:
pnpm dlx shadcn@4.18.0 add @siteplane/avatar @siteplane/buttonUsage
import { PencilIcon } from "lucide-react";
import {
Menu,
MenuTrigger,
MenuPopup,
MenuItem,
} from "@/siteplane/components/menu";
import { Button } from "@/siteplane/components/button";
<Menu>
<MenuTrigger render={<Button />}>Actions</MenuTrigger>
<MenuPopup>
<MenuItem>
<PencilIcon />
Edit
</MenuItem>
</MenuPopup>
</Menu>;Composition
Menu
├── MenuTrigger
└── MenuPopup
├── MenuGroup → MenuGroupLabel + items
├── MenuItem / CheckboxItem / RadioGroup
├── MenuSeparator
└── MenuSub → SubTrigger + MenuSubPopupAccount menu
Open account actions from an avatar button: a Button with profile="avatar" makes the portrait itself the trigger, with no box around it. A group label shows the signed-in user, MenuLinkItem renders a real link, and a submenu holds the theme choice.
Checkbox and radio items
Use MenuCheckboxItem for independent settings and MenuRadioGroup for one choice; both work controlled or with defaultChecked and defaultValue. variant="switch" only changes the indicator. The check draws in when an item is checked and out when it is not, the way the Checkbox check does, and appears instantly under reduced motion.
A radio item shows its check in the leading slot, where action rows show their icon. For identity rows that lead with a logo or an avatar, such as the workspaces of a switcher, set indicatorPosition="end": the row starts with its first child and ends with the check. The Sidebar examples use it for their workspace switcher.
Glass
Set variant="glass" on MenuPopup when the menu opens over a photo, a video or a color surface, and on a MenuSubPopup so its submenu matches. Rows, icons and their states stay the same. Glass shows every component with a glass variant.
The gradient only makes the glass visible. It is not part of the component.
API reference
Menu, MenuPortal and the group, radio and submenu parts follow Base UI Menu. Popup includes its Portal, Positioner and a scrolling viewport; do not add another Portal around it. LinkItem renders a native link. Shortcut renders kbd and does not register a shortcut. SubPopup opens on the inline-end side. MenuPrimitive exports the Base UI namespace. Styled className props are strings.
MenuCreateHandle is the detached-trigger handle factory. Shared menu style helpers are implementation support and are not re-exported from the Menu index.
| Prop | Type | Default | Description |
|---|---|---|---|
Menu | Positioner side | bottom | Preferred edge. |
Menu | start | center | end | center | Alignment. |
Menu | Positioner offset | 4 | Gap. |
Menu | Positioner offset | unset | Alignment offset. |
Menu | auto | trigger | content | at-least-trigger | auto | Width relationship to content/trigger. trigger matches the trigger; every other width is at most 20rem, or the trigger's width for at-least-trigger when it is wider. Every width stays within the space beside the trigger; a longer row label ends in an ellipsis and a group label wraps. |
Menu | Positioner anchor | trigger | Custom anchor. |
Menu | Portal.Props | unset | Portal options. |
Menu | default | glass | default | glass shows a tinted, blurred view of what lies behind the popup. |
Menu | default | destructive | default | Action tone. A destructive item colors its label and its icon red. |
Item / Group | boolean | unset (off) | Reserve the icon slot so the label lines up with icon rows. |
Menu | default | switch | default | Check or switch indicator; retains menuitemcheckbox semantics. |
Menu | start | end | start | Where the check shows: in the leading slot, or at the end of an identity row that leads with a logo or an avatar. |
Menu | sm | md | lg | xl | lg | Switch size. Menu rows stay compact at every control size, so the switch does not follow the provider. |
Menu | alignment / offset | start / 0 | Submenu positioning. |
Menu | offset | -5 unless align=center | Submenu alignment correction. |
Menu | default | glass | default | Set glass to match a glass parent menu. |
open / default | boolean | false | Visibility. |
on | (open, eventDetails) => void | unset | Visibility callback. |
Item. | MouseEventHandler | unset | Application action. |
Checkbox | boolean / callback | uncontrolled / unset | Controlled checked state. |
Radio | string / callback | uncontrolled / unset | Controlled choice. |
Menu | boolean | true | Closes the menu after activating a link. |
Menu | tone / boolean | default / unset | Link-row presentation. |
Modal, disabled, focus, dismissal and close-on-click behavior follow Base UI. A disabled item cannot be activated; the submenu trigger supplies the chevron. SubPopup accepts width plus the listed offsets, not arbitrary portal or anchor options.
The Menu module also exports DropdownMenu-prefixed aliases: DropdownMenu → Menu, DropdownMenuPortal → MenuPortal, DropdownMenuTrigger → MenuTrigger, DropdownMenuContent → MenuPopup, DropdownMenuGroup → MenuGroup, DropdownMenuItem → MenuItem, DropdownMenuCheckboxItem → MenuCheckboxItem, DropdownMenuRadioGroup → MenuRadioGroup, DropdownMenuRadioItem → MenuRadioItem, DropdownMenuLabel → MenuGroupLabel, DropdownMenuSeparator → MenuSeparator, DropdownMenuShortcut → MenuShortcut, DropdownMenuSub → MenuSub, DropdownMenuSubTrigger → MenuSubTrigger, DropdownMenuSubContent → MenuSubPopup, and DropdownMenuCreateHandle → MenuCreateHandle. They behave exactly like the Menu parts; see Dropdown Menu.
Usage notes
Start every action item with a fitting lucide icon, such as PencilIcon for Edit or Trash2Icon for Delete; checkbox and radio items show their own indicator instead. Arrow keys move through the items, including disabled ones, which cannot be activated. Enter activates an item, and Escape closes the menu with focus restoration. Use real links for navigation. Selection here is menu state, not native form submission. To open a dialog from a menu item, see Dialog.