Skip to content
Design System
Contact

Dropdown menu

Contextual actions with shortcuts, checkable items, radio groups and submenus.

ComponentsRadix DropdownMenu

Playground

Menus hold actions on one object. Keep them under about ten items, put the most common first and the destructive one last, behind a separator.

Preview
Open the menu and pick an itemShowing completed.

Props

Trigger
Side
Align
example.tsxtsx
1import { ChevronDown, Copy, Pencil, Share2, Trash2 } from "lucide-react"
2import { Button } from "@/components/ui/button"
3import {
4 DropdownMenu,
5 DropdownMenuCheckboxItem,
6 DropdownMenuContent,
7 DropdownMenuGroup,
8 DropdownMenuItem,
9 DropdownMenuLabel,
10 DropdownMenuSeparator,
11 DropdownMenuShortcut,
12 DropdownMenuSub,
13 DropdownMenuSubContent,
14 DropdownMenuSubTrigger,
15 DropdownMenuTrigger,
16} from "@/components/ui/dropdown-menu"
17
18<DropdownMenu>
19 <DropdownMenuTrigger asChild>
20 <Button variant="outline">
21 Project <ChevronDown data-icon="inline-end" />
22 </Button>
23 </DropdownMenuTrigger>
24 <DropdownMenuContent className="w-56">
25 <DropdownMenuLabel>Northwind portal</DropdownMenuLabel>
26 <DropdownMenuGroup>
27 <DropdownMenuItem>
28 <Pencil /> Rename
29 <DropdownMenuShortcut>⌘R</DropdownMenuShortcut>
30 </DropdownMenuItem>
31 <DropdownMenuItem>
32 <Copy /> Duplicate
33 <DropdownMenuShortcut>⌘D</DropdownMenuShortcut>
34 </DropdownMenuItem>
35 <DropdownMenuSub>
36 <DropdownMenuSubTrigger>
37 <Share2 /> Share
38 </DropdownMenuSubTrigger>
39 <DropdownMenuSubContent>
40 <DropdownMenuItem>Copy link</DropdownMenuItem>
41 <DropdownMenuItem>Invite people…</DropdownMenuItem>
42 <DropdownMenuItem>Export as PDF</DropdownMenuItem>
43 </DropdownMenuSubContent>
44 </DropdownMenuSub>
45 </DropdownMenuGroup>
46 <DropdownMenuSeparator />
47 <DropdownMenuLabel>Show</DropdownMenuLabel>
48 <DropdownMenuCheckboxItem checked={completed} onCheckedChange={setCompleted}>
49 Completed tasks
50 </DropdownMenuCheckboxItem>
51 <DropdownMenuCheckboxItem checked={subtasks} onCheckedChange={setSubtasks}>
52 Subtasks
53 </DropdownMenuCheckboxItem>
54 <DropdownMenuSeparator />
55 <DropdownMenuItem variant="destructive">
56 <Trash2 /> Delete project
57 <DropdownMenuShortcut>⌘⌫</DropdownMenuShortcut>
58 </DropdownMenuItem>
59 </DropdownMenuContent>
60</DropdownMenu>

Anatomy

The open state, drawn in place so every part can be inspected. The trigger keeps its pressed look through aria-expanded while the menu is open.

Open menu, rendered in place
Northwind portal
Rename ⌘R
Duplicate⌘D
Completed tasks
Share
Delete project
  1. DropdownMenuTriggerAny button via asChild. Gets aria-expanded and aria-haspopup.
  2. DropdownMenuLabelNon-interactive heading for a group.
  3. DropdownMenuItemHighlighted on hover or arrow keys; Enter selects.
  4. DropdownMenuShortcutHint only. Wire the shortcut separately.
  5. DropdownMenuCheckboxItemToggles with a check on the right.
  6. DropdownMenuSubTriggerOpens a submenu with → or hover.
  7. DropdownMenuSeparatorHairline between groups.
  8. Item variant="destructive"Last, after a separator, and confirmed.

States

States of the trigger. Open is the aria-expanded style shown in Anatomy; items have their own highlighted, checked and disabled states.

States
  • Defaultrest
  • Hover:hover
  • Focus:focus-visible
  • Loadingaria-busy
  • Disableddisabled
  • Erroraria-invalid
  • Successdata-state=success

Patterns

Row actions with a submenu and a confirm step before deleting, and a view menu whose checkbox and radio items change the list as you toggle them.

Row actions
Demo data
  • Customer portal

    Northwind

  • Billing migration

    Acme Corporation

  • Onboarding emails

    Globex

View options
Demo data

Open deals 4

Company OwnerStageAmount
Acme CorporationMC Maya ChenProposal$48,000
GlobexLP Leo ParkNegotiation$125,000
HooliTW Tom WeberLead$72,000
InitechSO Sara OkaforQualified$18,500

API

Built on Radix DropdownMenu. Content and items forward every Radix prop.

PropTypeDefaultDescription
open / onOpenChangeboolean / (open: boolean) => void—Control the menu, e.g. to open it from a keyboard shortcut.
modalbooleantrueBlocks outside pointer events and scroll while open.
Content side"top" | "right" | "bottom" | "left""bottom"Preferred side. Flips automatically when there is no room.
Content align"start" | "center" | "end""start"Alignment against the trigger. Use end for row actions on the right edge.
Content sideOffsetnumber4Gap between trigger and menu in px.
Item onSelect(event: Event) => void—Runs on click or Enter. Call event.preventDefault() to keep the menu open.
Item variant"default" | "destructive""default"Destructive tints the item red. Confirm or offer undo after it.
CheckboxItem checkedboolean | "indeterminate"—With onCheckedChange. Renders menuitemcheckbox.
RadioGroup valuestring—With onValueChange. Items render menuitemradio.

Accessibility

Keyboard

Open and focus the first item
EnterorSpaceor↓
Move between items
↑or↓
Open a submenu
→
Close the submenu
←
Typeahead to an item
A–Z
Close and return focus
Esc

Semantics and ARIA

  • The trigger gets aria-haspopup="menu" and aria-expanded; the content is a menu of menuitem, menuitemcheckbox and menuitemradio.
  • Focus moves into the menu on open and returns to the trigger on close. Use onCloseAutoFocus to redirect it, as Rename does to focus its input.
  • Icon-only triggers need an aria-label that names the object, e.g. “Actions for Customer portal”, not just “More”.
  • Shortcut hints are visual only. The shortcut must work elsewhere, and should not be the only way to reach the action.
  • Menus are for actions and settings. For picking a value in a form use Select; for navigation use links.
  • Destructive items are never the first item, are confirmed before they run and are announced through the toast region.