Dropdown menu
A list of actions or options that opens from a button, with groups, shortcuts, submenus, checkboxes and radio items.
npx prodular-ui add dropdown-menuAccount menu
Groups, shortcuts, a submenu and a destructive item at the end.
import { ChevronsUpDownIcon, CreditCardIcon, KeyboardIcon, LifeBuoyIcon, LogOutIcon, SettingsIcon, UserIcon, UsersIcon,} from "lucide-react"
import { Avatar, AvatarFallback } from "@/components/ui/avatar"import { Button } from "@/components/ui/button"import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger,} from "@/components/ui/dropdown-menu"
export default function DropdownMenuAccount() { return ( <DropdownMenu> <DropdownMenuTrigger render={<Button variant="ghost" className="h-10 gap-2.5 pr-2 pl-1.5" />}> <Avatar size="sm"> <AvatarFallback>MO</AvatarFallback> </Avatar> <span className="flex flex-col items-start leading-tight"> <span className="text-sm font-medium">Maya Okafor</span> <span className="text-xs font-normal text-muted-foreground">Halcyon</span> </span> <ChevronsUpDownIcon data-icon="inline-end" className="text-muted-foreground" /> </DropdownMenuTrigger> <DropdownMenuContent className="w-60"> <DropdownMenuGroup> <DropdownMenuLabel>maya@halcyon.dev</DropdownMenuLabel> <DropdownMenuItem> <UserIcon /> Profile <DropdownMenuShortcut>⇧⌘P</DropdownMenuShortcut> </DropdownMenuItem> <DropdownMenuItem> <CreditCardIcon /> Billing </DropdownMenuItem> <DropdownMenuItem> <SettingsIcon /> Settings <DropdownMenuShortcut>⌘,</DropdownMenuShortcut> </DropdownMenuItem> <DropdownMenuItem> <KeyboardIcon /> Keyboard shortcuts <DropdownMenuShortcut>?</DropdownMenuShortcut> </DropdownMenuItem> </DropdownMenuGroup> <DropdownMenuSeparator /> <DropdownMenuGroup> <DropdownMenuSub> <DropdownMenuSubTrigger> <UsersIcon /> Switch workspace </DropdownMenuSubTrigger> <DropdownMenuSubContent> <DropdownMenuItem>Halcyon</DropdownMenuItem> <DropdownMenuItem>Northgate Logistics</DropdownMenuItem> <DropdownMenuItem>Personal</DropdownMenuItem> </DropdownMenuSubContent> </DropdownMenuSub> <DropdownMenuItem> <LifeBuoyIcon /> Help and support </DropdownMenuItem> </DropdownMenuGroup> <DropdownMenuSeparator /> <DropdownMenuItem variant="destructive"> <LogOutIcon /> Log out <DropdownMenuShortcut>⇧⌘Q</DropdownMenuShortcut> </DropdownMenuItem> </DropdownMenuContent> </DropdownMenu> )}Display options
Radio items for one choice, checkbox items for many. closeOnClick false keeps the menu open while toggling.
"use client"
import * as React from "react"import { Settings2Icon } from "lucide-react"
import { Button } from "@/components/ui/button"import { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuTrigger,} from "@/components/ui/dropdown-menu"
const columns = ["Assignee", "Priority", "Labels", "Due date", "Estimate"]
export default function DropdownMenuOptions() { const [visible, setVisible] = React.useState<string[]>(["Assignee", "Priority", "Due date"]) const [grouping, setGrouping] = React.useState("status") return ( <DropdownMenu> <DropdownMenuTrigger render={<Button variant="outline" />}> <Settings2Icon data-icon="inline-start" /> Display </DropdownMenuTrigger> <DropdownMenuContent className="w-56"> <DropdownMenuGroup> <DropdownMenuLabel>Group by</DropdownMenuLabel> <DropdownMenuRadioGroup value={grouping} onValueChange={setGrouping}> <DropdownMenuRadioItem value="status">Status</DropdownMenuRadioItem> <DropdownMenuRadioItem value="assignee">Assignee</DropdownMenuRadioItem> <DropdownMenuRadioItem value="project">Project</DropdownMenuRadioItem> </DropdownMenuRadioGroup> </DropdownMenuGroup> <DropdownMenuSeparator /> <DropdownMenuGroup> <DropdownMenuLabel>Visible columns</DropdownMenuLabel> {columns.map((c) => ( <DropdownMenuCheckboxItem key={c} checked={visible.includes(c)} closeOnClick={false} onCheckedChange={(on) => setVisible((v) => (on ? [...v, c] : v.filter((x) => x !== c))) } > {c} </DropdownMenuCheckboxItem> ))} </DropdownMenuGroup> </DropdownMenuContent> </DropdownMenu> )}Anatomy
<DropdownMenu> <DropdownMenuTrigger render={<Button variant="outline" />}>Options</DropdownMenuTrigger> <DropdownMenuContent className="w-56"> <DropdownMenuGroup> <DropdownMenuLabel>Issue</DropdownMenuLabel> <DropdownMenuItem> <CopyIcon /> Duplicate <DropdownMenuShortcut>⌘D</DropdownMenuShortcut> </DropdownMenuItem> </DropdownMenuGroup> <DropdownMenuSeparator /> <DropdownMenuItem variant="destructive"> <Trash2Icon /> Delete </DropdownMenuItem> </DropdownMenuContent></DropdownMenu>Guidance
Use it when
- Use for actions on an object (Edit, Duplicate, Archive) or for view options behind one button.
- Use checkbox items for independent toggles and radio items for a single choice.
Avoid
- Choosing a value in a form. Use Select or Combobox.
- More than about 12 items. Split them into groups or a submenu, or use Command.
- Navigation between pages. Use Navigation menu or Sidebar.
Rules for AI agents
Published in llms-full.txt, the registry and the MCP server, so coding agents follow them when they build with this component.
- Give every item a verb or a destination as its label. Put the icon first, then the label, then DropdownMenuShortcut.
- Use variant="destructive" on the item that deletes or signs out, and put it last, after a separator.
- Group related items with DropdownMenuGroup and a DropdownMenuLabel in sentence case. Labels must be inside a group.
- Icons are 16px and muted automatically. Do not add size or color classes to them.
- Open from DropdownMenuTrigger with render={<Button />}. Icon only triggers need aria-label.
- Set a width on DropdownMenuContent with w-56 or similar. It never gets narrower than the trigger.
- Pass closeOnClick={false} on checkbox items when people usually toggle several at once.
API
DropdownMenuContent
| Prop | Type | Default | Description |
|---|---|---|---|
| align | "start" | "center" | "end" | "start" | Alignment against the trigger. |
| side | "top" | "right" | "bottom" | "left" | "bottom" | Preferred side. |
DropdownMenuItem
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | "default" | "destructive" | "default" | destructive colors the item and its hover state. |
| inset | boolean | false | Indents the label to line up with items that have icons. |
DropdownMenuCheckboxItem
| Prop | Type | Default | Description |
|---|---|---|---|
| checked / onCheckedChange | boolean / (checked: boolean) => void | Controlled check state. |
DropdownMenuRadioGroup
| Prop | Type | Default | Description |
|---|---|---|---|
| value / onValueChange | string / (value: string) => void | Controlled selection for radio items. |
Installation
The Prodular UI CLI adds the source to components/ui with everything it depends on. In a project that already uses shadcn/ui, the shadcn CLI installs it from the Prodular registry too. See Installation for the first setup.
npx prodular-ui add dropdown-menu# or, with the registry in components.jsonnpx shadcn@latest add @prodular/dropdown-menu