npx shadcn@latest add https://sdk-components.thesqd.com/r/dropdown-v2.jsonimport { DropdownV2 } from "@/components/ui/dropdown-v2";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)}
/>
);
}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.DropdownMenu
| Prop | Type | Default | Description |
|---|---|---|---|
trigger | ReactElement | — | Element rendered as the menu trigger (typically a `<Button>`). Presence of this (or `items`) switches on the flat API. |
items | DropdownMenuItemSpec[] | — | Menu entries. See the DropdownMenuItemSpec table below. |
label | ReactNode | — | Optional 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. |
sideOffset | number | 4 | Gap between the trigger and the popup. |
contentClassName | string | — | Class override for the content popup (e.g. a fixed width). |
open / onOpenChange / defaultOpen | Root props | — | Controlled/uncontrolled open state — forwarded to the underlying menu root. |
DropdownMenuItemSpec (each `items` entry)
| Prop | Type | Default | Description |
|---|---|---|---|
"separator" | string literal | — | Renders a divider between items. |
{ heading } | { heading: ReactNode } | — | Renders a non-interactive group label inline in the list. |
label | ReactNode | — | The item's text (for actionable entries). |
icon | ReactNode | — | Leading icon — typically a lucide icon. |
shortcut | ReactNode | — | Right-aligned shortcut hint (e.g. `⌘C`). |
onClick | (e) => void | — | Click handler for the item. |
variant | "default" | "destructive" | "default" | `destructive` tints the item red. |
disabled | boolean | — | Disable the item. |