Dropdown Menu

Dropdown Menu

A menu of actions opened from a trigger, built on Base UI. Supports checkbox and radio items, nested submenus and four density sizes.

Playground

size
checkboxItems
<DropdownMenu>
  <DropdownMenuTrigger render={<Button variant="outline" />}>
    Open Menu
  </DropdownMenuTrigger>
  <DropdownMenuContent className="w-48">
    <DropdownMenuItem>
      <User />
      Profile
    </DropdownMenuItem>
    <DropdownMenuItem>
      <Settings />
      Settings
    </DropdownMenuItem>
    <DropdownMenuSeparator />
    <DropdownMenuItem variant="destructive">
      <LogOut />
      Log out
    </DropdownMenuItem>
  </DropdownMenuContent>
</DropdownMenu>

Preview

DropdownMenuTrigger opens the menu – pass your button via the Base UI render prop. DropdownMenuContent positions the popup and items compose icons, text and DropdownMenuShortcut hints.

<DropdownMenu>
  <DropdownMenuTrigger render={<Button variant="outline" />}>
    Open Menu
  </DropdownMenuTrigger>
  <DropdownMenuContent className="w-56">
    <DropdownMenuGroup>
      <DropdownMenuLabel>My Account</DropdownMenuLabel>
      <DropdownMenuItem>
        <User />
        Profile
        <DropdownMenuShortcut>⇧⌘P</DropdownMenuShortcut>
      </DropdownMenuItem>
      <DropdownMenuItem>
        <CreditCard />
        Billing
        <DropdownMenuShortcut>⌘B</DropdownMenuShortcut>
      </DropdownMenuItem>
      <DropdownMenuItem>
        <Settings />
        Settings
        <DropdownMenuShortcut>⌘S</DropdownMenuShortcut>
      </DropdownMenuItem>
    </DropdownMenuGroup>
    <DropdownMenuSeparator />
    <DropdownMenuItem variant="destructive">
      <LogOut />
      Log out
      <DropdownMenuShortcut>⇧⌘Q</DropdownMenuShortcut>
    </DropdownMenuItem>
  </DropdownMenuContent>
</DropdownMenu>

Installation

npx shadcn@latest add https://espresso-base-ui.vercel.app/r/dropdown-menu.json

Usage

import {
  DropdownMenu,
  DropdownMenuCheckboxItem,
  DropdownMenuContent,
  DropdownMenuGroup,
  DropdownMenuItem,
  DropdownMenuLabel,
  DropdownMenuPortal,
  DropdownMenuRadioGroup,
  DropdownMenuRadioItem,
  DropdownMenuSeparator,
  DropdownMenuShortcut,
  DropdownMenuSub,
  DropdownMenuSubContent,
  DropdownMenuSubTrigger,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
<DropdownMenu>
  <DropdownMenuTrigger render={<Button variant="outline" />}>
    Open Menu
  </DropdownMenuTrigger>
  <DropdownMenuContent>
    <DropdownMenuItem>Option One</DropdownMenuItem>
    <DropdownMenuItem>Option Two</DropdownMenuItem>
  </DropdownMenuContent>
</DropdownMenu>

Sizes

size on DropdownMenuContent sets the item density for the whole menu via context – xs, sm (default), md and lg. Submenus inherit it, and individual items can override it with their own size prop.

<DropdownMenuContent size="xs">...</DropdownMenuContent>
<DropdownMenuContent size="sm">...</DropdownMenuContent>
<DropdownMenuContent size="md">...</DropdownMenuContent>
<DropdownMenuContent size="lg">...</DropdownMenuContent>

Checkbox and radio items

DropdownMenuCheckboxItem toggles independent options and DropdownMenuRadioGroup with DropdownMenuRadioItem picks one of a set – both show a trailing check indicator.

const [showStatusBar, setShowStatusBar] = React.useState(true)
const [position, setPosition] = React.useState("bottom")

<DropdownMenuCheckboxItem
  checked={showStatusBar}
  onCheckedChange={setShowStatusBar}
>
  Status Bar
</DropdownMenuCheckboxItem>

<DropdownMenuRadioGroup value={position} onValueChange={setPosition}>
  <DropdownMenuRadioItem value="top">Top</DropdownMenuRadioItem>
  <DropdownMenuRadioItem value="bottom">Bottom</DropdownMenuRadioItem>
  <DropdownMenuRadioItem value="right">Right</DropdownMenuRadioItem>
</DropdownMenuRadioGroup>

API reference

DropdownMenu is the Base UI Menu root and accepts its props – open, defaultOpen, onOpenChange and modal. The trigger supports the Base UI render prop; pass nativeButton={false} when the rendered element is not a native button.

DropdownMenuContent

PropTypeDefaultDescription
size"xs" | "sm" | "md" | "lg""sm"Item density for the whole menu, provided to items and submenus via context (reflected as data-size).
side"top" | "right" | "bottom" | "left""bottom"Which side of the trigger the menu opens on.
sideOffsetnumber4Gap between the trigger and the menu.
align"start" | "center" | "end""start"Alignment against the trigger.
alignOffsetnumber0Offset along the alignment axis.

DropdownMenuItem

PropTypeDefaultDescription
variant"default" | "destructive""default"Destructive items render in the destructive color, including their icon and shortcut.
size"xs" | "sm" | "md" | "lg"inheritedPer-item override of the size inherited from DropdownMenuContent.
insetboolean–Indent the item to line up with items that have a leading indicator.
disabledbooleanfalseDims the item and removes it from navigation.

DropdownMenuCheckboxItem

PropTypeDefaultDescription
checked / onCheckedChangeboolean / (checked) => void–Controlled checked state with a trailing check indicator.
insetboolean–Indent to align with inset items.

DropdownMenuRadioGroup

PropTypeDefaultDescription
value / onValueChangestring / (value) => void–Selected DropdownMenuRadioItem value and its change handler.

DropdownMenuSubContent

PropTypeDefaultDescription
side"top" | "right" | "bottom" | "left""right"Side of the sub-trigger the submenu opens on.
alignOffsetnumber-3Alignment offset tuned so submenu items line up with the parent item.
ComponentDescription
DropdownMenuTriggerOpens the menu (data-slot="dropdown-menu-trigger"); compose your button via the render prop.
DropdownMenuContentPortalled popup (data-slot="dropdown-menu-content") with slide/zoom animations and data-size.
DropdownMenuGroup / DropdownMenuLabelLogical item group (data-slot="dropdown-menu-group") with a small heading (data-slot="dropdown-menu-label", supports inset).
DropdownMenuItemAction row (data-slot="dropdown-menu-item") reflecting data-variant, data-size and data-inset.
DropdownMenuCheckboxItem / DropdownMenuRadioItemSelectable items (data-slot="dropdown-menu-checkbox-item" / "dropdown-menu-radio-item") with trailing check indicators.
DropdownMenuShortcutRight-aligned keyboard hint span (data-slot="dropdown-menu-shortcut").
DropdownMenuSeparatorThin divider between groups (data-slot="dropdown-menu-separator").
DropdownMenuSub / DropdownMenuSubTrigger / DropdownMenuSubContentNested submenu: root (data-slot="dropdown-menu-sub"), trigger with auto chevron (data-slot="dropdown-menu-sub-trigger") and side-opening popup (data-slot="dropdown-menu-sub-content").
DropdownMenuPortalPortals menu parts to the document body (data-slot="dropdown-menu-portal"); used internally by DropdownMenuContent.

Accessibility & styling hooks

Base UI renders the popup with role="menu" and items as menuitem / menuitemcheckbox / menuitemradio, with full keyboard support – arrows move the highlight, typeahead jumps to items, Enter activates and Escape closes. Every part exposes a data-slot attribute, and items reflect state as data-highlighted, data-disabled, data-inset, data-variant and data-size – target these from CSS for app-level overrides.

Search documentation

Search the component docs