Dropdown menu

Displays a menu of actions or options triggered by a button.

Installation
$Terminal
npx shadcn@latest add https://sdk-components.thesqd.com/r/dropdown-menu.json
Usage
Pass a `trigger` element and an `items` array. Each item is `"separator"`, `{ heading }`, or an actionable `{ label, icon?, shortcut?, onClick?, variant? }`.
TSImport
import { DropdownMenu } from "@/components/ui/dropdown-menu";
TSExample
import { ChevronDownIcon } from "lucide-react";
import { Button } from "@/components/ui/button";
import { DropdownMenu } from "@/components/ui/dropdown-menu";

export function Example() {
  return (
    <DropdownMenu
      label="Actions"
      trigger={<Button variant="outline">Open<ChevronDownIcon /></Button>}
      items={[
        { label: "Edit", onClick: () => {} },
        "separator",
        { label: "Delete", variant: "destructive", onClick: () => {} },
      ]}
    />
  );
}
Composition
Anatomy of the DropdownMenu flat API + its item spec.
DropdownMenu                       (single component — flat prop API)
├── trigger={<Button … />}          (element rendered as the menu trigger)
├── items={DropdownMenuItemSpec[]}  (entries — see below)
├── label={<ReactNode>}             (optional group label above the items)
├── size="default" | "sm"           ("sm" = identical menu, just more compact)
├── align="start" | "center" | "end"
├── side="top" | "right" | "bottom" | "left"
└── contentClassName="…"            (class override for the popup)

DropdownMenuItemSpec (each entry in items):
├── "separator"                     (a divider)
├── { heading }                     (a non-interactive group label)
└── { label, icon?, shortcut?, onClick?, variant?, disabled? }
        variant="default" | "destructive"

Need a checkbox/radio item, a submenu, or a custom layout? The slot exports —
DropdownMenuTrigger, DropdownMenuContent, DropdownMenuGroup, DropdownMenuLabel,
DropdownMenuItem, DropdownMenuCheckboxItem, DropdownMenuRadioGroup,
DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut,
DropdownMenuSub, DropdownMenuSubTrigger, DropdownMenuSubContent — are still
exported from the same file. Drop the flat API and compose them directly.
Actions
Pass a `trigger` element and an `items` array — each with an optional icon, plus a `variant="destructive"` delete after a `"separator"`.
With shortcuts
Add a `shortcut` to any item for a right-aligned keyboard hint, and a `label` for a group heading.
Compact (sm)
Pass `size="sm"` for an identical menu that's denser — tighter content padding, shorter items, smaller text + icons. The size flows to every item, label, separator, and submenu through context, so it also works with the compound slot API.
Checkbox items (escape hatch)
When the flat `items` API isn't enough, drop to the compound slots — here, stateful `DropdownMenuCheckboxItem`s.
API Reference
Props for the flat `<DropdownMenu>`. The compound slot exports remain available as the escape hatch.

DropdownMenu

PropTypeDefaultDescription
triggerReactElementElement rendered as the menu trigger (typically a `<Button>`). Presence of this (or `items`) switches on the flat API.
itemsDropdownMenuItemSpec[]Menu entries. See the DropdownMenuItemSpec table below.
labelReactNodeOptional group label rendered above the items.
size"default" | "sm""default"`sm` renders an identical menu, just more compact (tighter padding, shorter items, smaller text + icons). Flows to every nested slot via context; also accepted on `DropdownMenuContent` and individual slots.
align"start" | "center" | "end""start"Alignment of the popup relative to the trigger.
side"top" | "right" | "bottom" | "left""bottom"Which side of the trigger the popup opens on.
sideOffsetnumber4Gap between the trigger and the popup.
contentClassNamestringClass override for the content popup (e.g. a fixed width).
open / onOpenChange / defaultOpenRoot propsControlled/uncontrolled open state — forwarded to the underlying menu root.

DropdownMenuItemSpec (each `items` entry)

PropTypeDefaultDescription
"separator"string literalRenders a divider between items.
{ heading }{ heading: ReactNode }Renders a non-interactive group label inline in the list.
labelReactNodeThe item's text (for actionable entries).
iconReactNodeLeading icon — typically a lucide icon.
shortcutReactNodeRight-aligned shortcut hint (e.g. `⌘C`).
onClick(e) => voidClick handler for the item.
variant"default" | "destructive""default"`destructive` tints the item red.
disabledbooleanDisable the item.