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-v2.json
Usage
Pass a `trigger` element and an `items` array. Drive selection with `value` / `onValueChange` — a number for single-select, or add `multiple` and use an array for multi-select.
TSImport
import { DropdownV2 } from "@/components/ui/dropdown-v2";
TSExample
import { useState } from "react";
import {
  ChevronDownIcon,
  LayoutGridIcon,
  ListIcon,
  KanbanIcon,
  CalendarIcon,
  TableIcon,
} from "lucide-react";
import { Button } from "@/components/ui/button";
import { DropdownV2 } from "@/components/ui/dropdown-v2";

const VIEWS = [
  { label: "Grid", icon: LayoutGridIcon },
  { label: "List", icon: ListIcon },
  { label: "Board", icon: KanbanIcon },
  { label: "Calendar", icon: CalendarIcon },
  { label: "Table", icon: TableIcon },
];

export function Example() {
  const [selected, setSelected] = useState(0);

  return (
    <DropdownV2
      trigger={
        <Button variant="outline">
          {`${VIEWS[selected].label} view`}
          <ChevronDownIcon />
        </Button>
      }
      items={VIEWS}
      value={selected}
      onValueChange={(v) => setSelected(v as number)}
    />
  );
}
Composition
Anatomy of the v2 compound API.
DropdownV2                          (single component — flat prop API)
├── trigger={<Button … />}          (element that opens the menu)
├── items={DropdownV2ItemSpec[] | DropdownV2Group[]}  (flat or grouped)
├── value={number | number[]}       (selected index, or indices when multiple)
├── onValueChange={(v) => …}        (v is a number, or number[] when multiple)
├── multiple                        (toggle several; menu stays open)
├── side / align / sideOffset       (positioning)
└── className="…"                   (class override for the popup panel)

DropdownV2ItemSpec (each entry in a flat items array):
└── { label, icon?, disabled?, closeOnClick? }

DropdownV2Group (pass an array of these for section headings + separators):
├── { heading?, items: DropdownV2ItemSpec[] }   (value indexes the flattened items)
└── { content: ReactNode }                      (rich block, e.g. a header card)

Need an always-open inline panel or a custom layout? The compound slot exports
— DropdownMenu, DropdownTrigger, DropdownContent, MenuItem, plus Dropdown /
DropdownLabel / DropdownSeparator — remain available from the same file.
Single-select
Pass a `trigger` and `items`; drive selection with `value` / `onValueChange`. Proximity-hover overlays, a brand-colored selection, and a check that draws in.
Multi-select
Add `multiple` to toggle several options at once — the menu stays open while you pick and each selected row goes brand with a check.
Groups
Pass nested `{ heading, items }` groups and the menu renders section headings with a separator between groups. `value` indexes across the flattened items.
Action menu
Omit `value` / `onValueChange` and give each item an `onSelect` — the rows act as buttons (copy to clipboard, fire a toast, open a page) with no selection state. A group entry can carry rich `content` (e.g. the header card) instead of items.
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.