Skip to content
Primitives

Dropdown Menu

Menu surface with signal-wash highlights and destructive items.

● LIVE

[ interactive — use the trigger to open ]

npx shadcn@latest add https://okibi.cndr.dev/r/dropdown-menu.json

Installation

Install the theme first, then add the component:

npx shadcn@latest add https://okibi.cndr.dev/r/dropdown-menu.json

Install the required dependencies:

npm install @radix-ui/react-dropdown-menu lucide-react

Copy the source from the Code tab above into components/ui/dropdown-menu.tsx. It uses the cn helper and the okibi theme tokens — install the theme first if you haven't.

Usage

import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuLabel,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"

<DropdownMenu>
  <DropdownMenuTrigger>Open</DropdownMenuTrigger>
  <DropdownMenuContent>
    <DropdownMenuLabel>Actions</DropdownMenuLabel>
    <DropdownMenuSeparator />
    <DropdownMenuItem>Purge logs</DropdownMenuItem>
  </DropdownMenuContent>
</DropdownMenu>

Anatomy

<DropdownMenu>
  <DropdownMenuTrigger />
  <DropdownMenuContent>
    <DropdownMenuLabel />        {/* group caption (non-interactive) */}
    <DropdownMenuSeparator />
    <DropdownMenuGroup>
      <DropdownMenuItem>
        Action <DropdownMenuShortcut />   {/* trailing mono hotkey */}
      </DropdownMenuItem>
    </DropdownMenuGroup>
    <DropdownMenuSub>           {/* nested submenu */}
      <DropdownMenuSubTrigger />
      <DropdownMenuSubContent />
    </DropdownMenuSub>
  </DropdownMenuContent>
</DropdownMenu>

Examples

DropdownMenuCheckboxItem keeps multi-select options (view toggles, filters) inside the menu, each with its own checked state.

● LIVE

[ interactive — use the trigger to open ]

DropdownMenuRadioGroup binds a set of DropdownMenuRadioItems to a single value for mutually-exclusive choices.

● LIVE

[ interactive — use the trigger to open ]

The full menu surface — a nested DropdownMenuSub, DropdownMenuShortcuts, an inset item, and a labeled group.

● LIVE

[ interactive — use the trigger to open ]

API Reference

PropTypeDefaultDescription
sideOffsetnumber4Gap in pixels between the trigger and the menu.
align"start" | "center" | "end""start"Alignment against the trigger (Radix default).
PropTypeDefaultDescription
variant"default" | "destructive""default"destructive washes scarlet on focus for irreversible actions.
insetbooleanfalsePad the left edge to align with items that carry an indicator.
disabledbooleanfalseSkip the item in keyboard navigation and dim it.
onSelect(event: Event) => voidFires when the item is chosen.
PropTypeDefaultDescription
checkedbooleanControlled checked state; renders the indicator.
onCheckedChange(checked: boolean) => voidFires when toggled.
PropTypeDefaultDescription
valuestringThe selected DropdownMenuRadioItem value.
onValueChange(value: string) => voidFires when a radio item is chosen.
PropTypeDefaultDescription
insetbooleanfalsePad the left edge to align with indicator items.
PropTypeDefaultDescription
insetbooleanfalsePad the left edge to align with indicator items.

Accessibility

  • Radix manages roving focus, type-ahead, arrow-key navigation, and Escape to close.
  • DropdownMenuLabel is a non-interactive caption — it is not focusable and announces as a group label, not a command.
  • DropdownMenuCheckboxItem and DropdownMenuRadioItem expose their checked state to assistive tech via Radix item indicators.
  • Disabled items (data-[disabled]) are skipped by keyboard navigation and dimmed to opacity-60.
  • Destructive items use text-destructive-spark so the scarlet reads at WCAG AA on the popover surface.

Guidelines

Do

  • Group related commands and split sections with DropdownMenuSeparator; caption a group with DropdownMenuLabel.
  • Mark the variant='destructive' on irreversible items so they wash scarlet on focus.
  • Pair frequent items with a DropdownMenuShortcut that mirrors a real keybinding.

Don't

  • Don't reach for a dropdown menu when you need form fields or rich content — use a Popover or Dialog.
  • Don't bury primary navigation in a submenu; reserve DropdownMenuSub for secondary, lower-traffic actions.
  • Don't rely on DropdownMenuLabel as a control — it can't be focused or activated.

On this page