Menu

Menu

Markdown

A contextual list of actions and choices with groups, persistent selection, and nested submenus.

Use Menu for actions related to a trigger or nearby object. Use Select when the control’s primary purpose is choosing a form value.

Action menu

Installation

$npx shadcn@latest add @patchui/menu

The copied source is available in the registry JSON. The canonical implementation lives in packages/react/src/components/menu.tsx.

Usage

<Menu>
  <MenuTrigger render={<Button variant="secondary" />}>
    Actions
  </MenuTrigger>
  <MenuPopup>
    <MenuItem>Duplicate</MenuItem>
    <MenuItem>Rename</MenuItem>
    <MenuDivider />
    <MenuItem type="error">Delete</MenuItem>
  </MenuPopup>
</Menu>

MenuTrigger supplies open-state semantics to the rendered trigger. MenuItem closes the menu by default unless closeOnClick={false} is set.

Composition

Menu
├── MenuTrigger
└── MenuPopup
    ├── MenuSection
    │   ├── MenuGroupLabel
    │   └── MenuItem
    ├── MenuCheckboxItem
    ├── MenuRadioGroup
    │   └── MenuRadioItem
    ├── MenuDivider
    └── MenuSub
        ├── MenuSubTrigger
        └── MenuSubPopup

Examples

Persistent choices

Use checkbox items for independent toggles and a radio group for one choice from a set. These communicate persistent state rather than temporary pointer or keyboard highlight.

Persistent choices

Use a submenu when a related action set would make the top-level menu difficult to scan. Keep nesting shallow.

Submenu

API reference

PropTypeDefaultDescription
MenuPopup.density"compact" | "comfortable""comfortable"Selects dense or larger item rows.
MenuItem.type"default" | "error""default"Adds destructive action presentation.
MenuItem.selectedbooleanfalseDisplays a trailing check for a current single choice.
MenuItem.descriptionReactNode-Adds a secondary line below the item label.
MenuItem.hrefstring-Renders the item as an anchor while preserving menu behavior.
MenuCheckboxItem.checked / onCheckedChangeboolean / (checked: boolean) => void-Controls an independent persistent choice without closing the menu.
MenuRadioGroup.value / onValueChangestring / (value: string) => void-Controls one selected value across MenuRadioItem children.

MenuPopup inherits Base UI positioning props and defaults to side="bottom", align="start", and sideOffset={4}. MenuSection supplies a labeled group, while prefix, suffix, and MenuShortcut add supporting content to an item.

Keyboard behavior

  • Arrow keys move through enabled menu items. Home and End move to the first or last item.
  • Enter or Space activates the highlighted item. Typing moves to a matching item.
  • Escape closes the current menu and returns focus through the underlying Base UI behavior.
  • Arrow Right opens a submenu from its trigger; Arrow Left returns to the parent menu.
  • selected, checked, and radio state are persistent application state and remain distinct from temporary highlight.

Mobile behavior

Below the md breakpoint, a top-level MenuPopup becomes a centered panel with narrow viewport gutters, a backdrop, comfortable density, and locked body scrolling. Submenus remain anchored to their parent item.