skrewww

Navigation

Menu

Menu is a compact command surface for contextual actions — distinct from Select (form values) and Popover (supplementary content).

Placement (bottom default) · Item states (Default/Hover/Disabled/Destructive)

betaReact AvailableFigma AvailableDocs Partial
React last updated
2026-07-12
Documentation last updated
2026-06-01
Accessibility target
WCAG 2.2 AA (target)
Version
0.4.0-beta

Known open questions

  • Checkbox and radio menu items are not confirmed in Figma — deferred.
  • Submenus and Context Menu are separate future components.
  • Dropdown Menu is documented as a usage pattern, not a duplicate public component.

Live preview

Menu is a compact command list — not for navigation landmarks or form value selection. Dropdown Menu is this same Menu pattern opened from a trigger.

Project actions

Last action: No action yet

Disabled item and keyboard navigation

Groups and separators

Controlled open state

Long menu with internal scrolling

Menu inside Dialog

Purpose

A compact collection of commands or actions opened from a trigger — use for application commands, contextual actions, overflow menus, and item-specific operations.

Anatomy

Menu = trigger button + floating menu surface + menuitem rows with optional icons, shortcuts, groups, labels, and separators.

Variants and states

default · destructive

When to use

Application commands, contextual actions, overflow actions, view or sorting commands, and item-specific operations that execute immediately.

When not to use

Ordinary site navigation, article link lists, form option selection (use Select), tabs, breadcrumbs, sidebar navigation, long content, or complex forms.

Accessibility

role="menu" on the menu surface with role="menuitem" rows, aria-haspopup="menu" and aria-expanded on the trigger, roving keyboard focus, typeahead search, Escape dismissal, and Tab exits without trapping focus.

Keyboard behavior

Arrow Up/Down move between enabled items. Home/End jump to boundaries. Enter and Space activate. Printable keys typeahead-match item labels. Escape closes and restores trigger focus. Tab and Shift+Tab close without trapping focus.

Common mistakes

Using Menu for primary navigation links, using Menu where Select is needed for form values, or nesting interactive controls inside menu items.

Properties

Compound API: Menu, MenuTrigger, MenuContent, MenuItem, MenuGroup, MenuLabel, MenuSeparator. MenuItem supports icon, shortcut, destructive styling, disabled state, and onSelect.

What is the difference between Menu and Popover?

Menu contains commands with menuitem semantics and a managed keyboard model. Popover holds supplementary or interactive content without command-list semantics.

What is the difference between Menu and Select?

Select chooses one form field value with combobox/listbox semantics. Menu executes commands and does not submit a single canonical field value.

Should ordinary navigation links use Menu semantics?

No. Persistent navigation belongs in nav landmarks, breadcrumbs, or tabs. Menu is for transient command lists.

Does Tab move through Menu items?

No. Tab closes the Menu and continues normal document focus order.

Tokens used

menu/surfacemenu/item-textmenu/item-hover-surfacesemantic/focus-ringsemantic/action/danger

Component API

PropTypeDefaultDescription
openbooleanControlled open state.
defaultOpenbooleanInitial open state.
onOpenChange(open: boolean) => voidOpen state callback.
placementPopoverPlacement"bottom"Preferred placement.
alignPopoverAlign"start"Alignment relative to trigger.
loopbooleanfalseWhether arrow navigation wraps.
closeOnSelectbooleantrueClose after item activation.
onSelect(event: Event) => voidMenuItem activation callback.

React example

Copy React example
"use client";

import {
  Menu,
  MenuContent,
  MenuItem,
  MenuSeparator,
  MenuTrigger,
} from "@/components/ui/Menu";
import { Button } from "@/components/ui/Button";

export function Example() {
  return (
    <Menu>
      <MenuTrigger>
        <Button type="button">Project actions</Button>
      </MenuTrigger>
      <MenuContent>
        <MenuItem onSelect={() => {}}>Edit profile</MenuItem>
        <MenuItem onSelect={() => {}}>Duplicate</MenuItem>
        <MenuSeparator />
        <MenuItem destructive onSelect={() => {}}>
          Delete project
        </MenuItem>
      </MenuContent>
    </Menu>
  );
}