DropdownMenu
Dropdown menu component with customizable items, icons, separators, checkboxes, radio groups, and submenus. Based on Radix UI DropdownMenu.
Component
Import
tsx
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
  DropdownMenuSeparator,
  DropdownMenuLabel,
  DropdownMenuCheckboxItem,
  DropdownMenuRadioGroup,
  DropdownMenuRadioItem,
  DropdownMenuSub,
  DropdownMenuSubTrigger,
  DropdownMenuSubContent,
  DropdownMenuSelectableItem,
  DropdownMenuItemWithActions,
  DropdownMenuAddItem,
} from "@/components/ui/dropdown-menu";
import { DesignIcon } from "@/components/ui/design-icon";
Item Height
32px (h-8)
Font Size
13px
Alignment
start, center, end
Features
Icons, separators, checkboxes, radios, submenus

Core Components

Basic building blocks for dropdown menus

Props
PropTypeDefaultDescription
DropdownMenuContainer-Root component, wraps everything
DropdownMenuTriggerTrigger-Element that opens the menu. Use asChild with DesignButton
DropdownMenuContentContent-The popup container. Props: align (start|center|end), sideOffset
DropdownMenuItemItem-Clickable menu item. Props: variant (default|destructive), disabled
DropdownMenuSeparatorDivider-Visual separator between groups
DropdownMenuLabelText-Non-interactive label for grouping items

Selection Components

Components for building selection menus

Props
PropTypeDefaultDescription
DropdownMenuCheckboxItemToggle-Checkbox item. Props: checked, onCheckedChange
DropdownMenuRadioGroupContainer-Radio group container. Props: value, onValueChange
DropdownMenuRadioItemRadio-Radio option. Props: value
DropdownMenuSelectableItemSelection-Single selection with check. Props: selected, onSelect
DropdownMenuItemWithActionsSelection-Selection with edit/delete buttons. Props: selected, onSelect, onEdit, onDelete
DropdownMenuAddItemAction-Add new item button. Props: onClick

Submenu Components

Components for nested menus

Props
PropTypeDefaultDescription
DropdownMenuSubContainer-Submenu container
DropdownMenuSubTriggerTrigger-Item that opens submenu (shows arrow)
DropdownMenuSubContentContent-Submenu popup content
Common Patterns

Basic Actions Menu

Simple menu with icons
<DropdownMenu>
  <DropdownMenuTrigger asChild>
    <DesignButton variant="tertiary" size="icon">
      <DesignIcon name="more" />
    </DesignButton>
  </DropdownMenuTrigger>
  <DropdownMenuContent align="end">
    <DropdownMenuItem>
      <DesignIcon name="edit" />
      Edit
    </DropdownMenuItem>
    <DropdownMenuItem>
      <DesignIcon name="duplicate" />
      Duplicate
    </DropdownMenuItem>
    <DropdownMenuSeparator />
    <DropdownMenuItem variant="destructive">
      <DesignIcon name="delete" />
      Delete
    </DropdownMenuItem>
  </DropdownMenuContent>
</DropdownMenu>

With Labels and Groups

Organized with section labels
<DropdownMenuContent>
  <DropdownMenuLabel>File Actions</DropdownMenuLabel>
  <DropdownMenuItem>
    <DesignIcon name="save" />
    Download
  </DropdownMenuItem>
  <DropdownMenuSeparator />
  <DropdownMenuLabel>Edit Actions</DropdownMenuLabel>
  <DropdownMenuItem>
    <DesignIcon name="edit" />
    Edit
  </DropdownMenuItem>
</DropdownMenuContent>

Checkbox Menu

Toggle options
const [checked, setChecked] = useState(true);

<DropdownMenuContent>
  <DropdownMenuLabel>Settings</DropdownMenuLabel>
  <DropdownMenuCheckboxItem
    checked={checked}
    onCheckedChange={setChecked}
  >
    <DesignIcon name="analytics" />
    Show notifications
  </DropdownMenuCheckboxItem>
</DropdownMenuContent>

Radio Group

Single selection
const [value, setValue] = useState("bottom");

<DropdownMenuContent>
  <DropdownMenuLabel>Position</DropdownMenuLabel>
  <DropdownMenuRadioGroup value={value} onValueChange={setValue}>
    <DropdownMenuRadioItem value="top">Top</DropdownMenuRadioItem>
    <DropdownMenuRadioItem value="bottom">Bottom</DropdownMenuRadioItem>
    <DropdownMenuRadioItem value="left">Left</DropdownMenuRadioItem>
  </DropdownMenuRadioGroup>
</DropdownMenuContent>

Selectable with Actions

Items with edit/delete on hover
<DropdownMenuContent>
  <DropdownMenuLabel>Styles</DropdownMenuLabel>
  <DropdownMenuSelectableItem
    selected={!selectedId}
    onSelect={() => setSelectedId(null)}
  >
    None
  </DropdownMenuSelectableItem>
  <DropdownMenuItemWithActions
    selected={selectedId === "pro"}
    onSelect={() => setSelectedId("pro")}
    onEdit={() => handleEdit("pro")}
    onDelete={() => handleDelete("pro")}
  >
    Professional
  </DropdownMenuItemWithActions>
  <DropdownMenuSeparator />
  <DropdownMenuAddItem onClick={handleAdd}>
    Add style...
  </DropdownMenuAddItem>
</DropdownMenuContent>

Submenu

Nested menu
<DropdownMenuContent>
  <DropdownMenuItem>
    <DesignIcon name="edit" />
    Edit
  </DropdownMenuItem>
  <DropdownMenuSub>
    <DropdownMenuSubTrigger>
      <DesignIcon name="favorite" />
      Favorites
    </DropdownMenuSubTrigger>
    <DropdownMenuSubContent>
      <DropdownMenuItem>Add to favorites</DropdownMenuItem>
      <DropdownMenuItem>Remove from favorites</DropdownMenuItem>
    </DropdownMenuSubContent>
  </DropdownMenuSub>
</DropdownMenuContent>
When to Use
1

Draft/item actions (more button)

Use icon trigger with align="end"

<DropdownMenu>
  <DropdownMenuTrigger asChild>
    <DesignButton variant="tertiary" size="icon">
      <DesignIcon name="more" />
    </DesignButton>
  </DropdownMenuTrigger>
  <DropdownMenuContent align="end">
    <DropdownMenuItem><DesignIcon name="open" />Open</DropdownMenuItem>
    <DropdownMenuItem><DesignIcon name="duplicate" />Duplicate</DropdownMenuItem>
    <DropdownMenuSeparator />
    <DropdownMenuItem variant="destructive"><DesignIcon name="delete" />Delete</DropdownMenuItem>
  </DropdownMenuContent>
</DropdownMenu>
2

User account menu

Profile trigger with logout as destructive

<DropdownMenuContent align="end">
  <DropdownMenuItem><DesignIcon name="user-center" />Profile</DropdownMenuItem>
  <DropdownMenuItem><DesignIcon name="setting" />Settings</DropdownMenuItem>
  <DropdownMenuSeparator />
  <DropdownMenuItem variant="destructive"><DesignIcon name="sign-out" />Log out</DropdownMenuItem>
</DropdownMenuContent>
3

Selection with management (styles, labels, categories)

Use SelectableItem + ItemWithActions + AddItem

<DropdownMenuContent>
  <DropdownMenuLabel>Labels</DropdownMenuLabel>
  <DropdownMenuSelectableItem>None</DropdownMenuSelectableItem>
  <DropdownMenuItemWithActions
    selected
    onEdit={handleEdit}
    onDelete={handleDelete}
  >
    Important
  </DropdownMenuItemWithActions>
  <DropdownMenuSeparator />
  <DropdownMenuAddItem onClick={handleAdd}>Create label...</DropdownMenuAddItem>
</DropdownMenuContent>
Do

Always use asChild on DropdownMenuTrigger

<DropdownMenuTrigger asChild>
  <DesignButton variant="tertiary" size="icon">
    <DesignIcon name="more" />
  </DesignButton>
</DropdownMenuTrigger>

Add icons to menu items for better scannability

<DropdownMenuItem>
  <DesignIcon name="edit" />
  Edit
</DropdownMenuItem>

Use variant="destructive" for delete/remove actions

<DropdownMenuItem variant="destructive">
  <DesignIcon name="delete" />
  Delete
</DropdownMenuItem>

Group related items with separators

<DropdownMenuItem>Edit</DropdownMenuItem>
<DropdownMenuItem>Duplicate</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem variant="destructive">Delete</DropdownMenuItem>
Don't

Don't forget asChild - it prevents nested button issues

// ❌ Bad
<DropdownMenuTrigger>
  <DesignButton>Open</DesignButton>
</DropdownMenuTrigger>

// βœ… Good
<DropdownMenuTrigger asChild>
  <DesignButton>Open</DesignButton>
</DropdownMenuTrigger>

Don't mix CheckboxItem and RadioItem in the same group

// ❌ Bad - confusing UX
<DropdownMenuCheckboxItem />
<DropdownMenuRadioItem />

// βœ… Good - use one type per section
<DropdownMenuRadioGroup>
  <DropdownMenuRadioItem />
  <DropdownMenuRadioItem />
</DropdownMenuRadioGroup>

Don't put destructive actions at the top

// ❌ Bad - dangerous
<DropdownMenuItem variant="destructive">Delete</DropdownMenuItem>
<DropdownMenuItem>Edit</DropdownMenuItem>

// βœ… Good - destructive at bottom
<DropdownMenuItem>Edit</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem variant="destructive">Delete</DropdownMenuItem>

Visual Examples

Interactive examples showing all variants

Basic Actions

Edit, duplicate, delete pattern

<DropdownMenuItem><DesignIcon name="edit" />Edit</DropdownMenuItem>
<DropdownMenuItem variant="destructive"><DesignIcon name="delete" />Delete</DropdownMenuItem>

With Labels

Grouped with section headers

<DropdownMenuLabel>Actions</DropdownMenuLabel>
<DropdownMenuItem>...</DropdownMenuItem>

Checkbox Items

Toggle settings

<DropdownMenuCheckboxItem checked={checked} onCheckedChange={setChecked}>
  Option
</DropdownMenuCheckboxItem>

Radio Group

Single selection

<DropdownMenuRadioGroup value={value} onValueChange={setValue}>
  <DropdownMenuRadioItem value="opt">Option</DropdownMenuRadioItem>
</DropdownMenuRadioGroup>

Submenu

Nested menu with arrow

<DropdownMenuSub>
  <DropdownMenuSubTrigger>Submenu</DropdownMenuSubTrigger>
  <DropdownMenuSubContent>...</DropdownMenuSubContent>
</DropdownMenuSub>

Selectable with Actions

Edit/delete on hover

<DropdownMenuItemWithActions
  selected={selected}
  onSelect={handleSelect}
  onEdit={handleEdit}
  onDelete={handleDelete}
>
  Item
</DropdownMenuItemWithActions>