Dropdown Menu
Displays a menu to the user — such as a set of actions or functions — triggered by a button, built on the Base UI Menu primitive.
"use client";
import { Button } from "@/registry/base/ui/button";
import {
DropdownMenu,
DropdownMenuCheckboxItem,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuRadioGroup,
DropdownMenuRadioItem,
DropdownMenuSeparator,
DropdownMenuShortcut,
DropdownMenuSub,
DropdownMenuSubContent,
DropdownMenuSubTrigger,
DropdownMenuTrigger,
} from "@/registry/base/ui/dropdown-menu";
export default function DropdownMenuDemo() {
return (
<DropdownMenu>
<DropdownMenuTrigger render={<Button variant="outline">Open menu</Button>} />
<DropdownMenuContent align="start" className="w-56">
<DropdownMenuGroup>
<DropdownMenuLabel>My Account</DropdownMenuLabel>
<DropdownMenuItem>
Profile
<DropdownMenuShortcut>⇧⌘P</DropdownMenuShortcut>
</DropdownMenuItem>
<DropdownMenuItem>
Billing
<DropdownMenuShortcut>⌘B</DropdownMenuShortcut>
</DropdownMenuItem>
<DropdownMenuItem>
Settings
<DropdownMenuShortcut>⌘S</DropdownMenuShortcut>
</DropdownMenuItem>
</DropdownMenuGroup>
<DropdownMenuSeparator />
<DropdownMenuSub>
<DropdownMenuSubTrigger>Invite users</DropdownMenuSubTrigger>
<DropdownMenuSubContent>
<DropdownMenuItem>Email</DropdownMenuItem>
<DropdownMenuItem>Message</DropdownMenuItem>
</DropdownMenuSubContent>
</DropdownMenuSub>
<DropdownMenuSeparator />
<DropdownMenuCheckboxItem defaultChecked>
Status bar
</DropdownMenuCheckboxItem>
<DropdownMenuCheckboxItem>Activity bar</DropdownMenuCheckboxItem>
<DropdownMenuSeparator />
<DropdownMenuRadioGroup defaultValue="bottom">
<DropdownMenuLabel>Panel position</DropdownMenuLabel>
<DropdownMenuRadioItem value="top">Top</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="bottom">Bottom</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="right">Right</DropdownMenuRadioItem>
</DropdownMenuRadioGroup>
<DropdownMenuSeparator />
<DropdownMenuItem variant="destructive">Log out</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
}
Installation
npx shadcn@latest add https://sevenui.dev/r/dropdown-menu.jsonUsage
"use client";
import { Button } from "@/components/ui/button";
import {
DropdownMenu,
DropdownMenuCheckboxItem,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuRadioGroup,
DropdownMenuRadioItem,
DropdownMenuSeparator,
DropdownMenuShortcut,
DropdownMenuSub,
DropdownMenuSubContent,
DropdownMenuSubTrigger,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
export default function DropdownMenuDemo() {
return (
<DropdownMenu>
<DropdownMenuTrigger render={<Button variant="outline">Open menu</Button>} />
<DropdownMenuContent align="start" className="w-56">
<DropdownMenuGroup>
<DropdownMenuLabel>My Account</DropdownMenuLabel>
<DropdownMenuItem>
Profile
<DropdownMenuShortcut>⇧⌘P</DropdownMenuShortcut>
</DropdownMenuItem>
<DropdownMenuItem>
Billing
<DropdownMenuShortcut>⌘B</DropdownMenuShortcut>
</DropdownMenuItem>
<DropdownMenuItem>
Settings
<DropdownMenuShortcut>⌘S</DropdownMenuShortcut>
</DropdownMenuItem>
</DropdownMenuGroup>
<DropdownMenuSeparator />
<DropdownMenuSub>
<DropdownMenuSubTrigger>Invite users</DropdownMenuSubTrigger>
<DropdownMenuSubContent>
<DropdownMenuItem>Email</DropdownMenuItem>
<DropdownMenuItem>Message</DropdownMenuItem>
</DropdownMenuSubContent>
</DropdownMenuSub>
<DropdownMenuSeparator />
<DropdownMenuCheckboxItem defaultChecked>
Status bar
</DropdownMenuCheckboxItem>
<DropdownMenuCheckboxItem>Activity bar</DropdownMenuCheckboxItem>
<DropdownMenuSeparator />
<DropdownMenuRadioGroup defaultValue="bottom">
<DropdownMenuLabel>Panel position</DropdownMenuLabel>
<DropdownMenuRadioItem value="top">Top</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="bottom">Bottom</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="right">Right</DropdownMenuRadioItem>
</DropdownMenuRadioGroup>
<DropdownMenuSeparator />
<DropdownMenuItem variant="destructive">Log out</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
}
API reference
DropdownMenu
Extends the Base UI Menu Root — all its props apply.
| Prop | Type | Default |
|---|---|---|
open / defaultOpen |
boolean |
false |
onOpenChange |
(open: boolean) => void |
— |
modal |
boolean |
true |
loopFocus |
boolean — arrow keys wrap (not loop) |
true |
closeParentOnEsc |
boolean — Esc in a submenu closes the parent |
— |
DropdownMenuTrigger
The only part rendering a native <button>; accepts the render prop.
Hover-opening lives here (and on DropdownMenuSubTrigger), not the
Root.
| Prop | Type | Default |
|---|---|---|
openOnHover |
boolean |
false |
delay |
number |
100 (ms) |
DropdownMenuItem, DropdownMenuCheckboxItem, DropdownMenuRadioItem
All render <div> elements — disabled styling comes from the
data-disabled attribute, not the disabled HTML attribute.
closeOnClick defaults differ: true on Item, false on
CheckboxItem/RadioItem, so toggling options keeps the menu open.
| Prop | Type | Default |
|---|---|---|
variant (Item) |
"default" | "destructive" |
"default" |
inset |
boolean — align with checkables |
false |
checked / onCheckedChange (CheckboxItem) |
boolean / callback |
— |
value (RadioItem) |
string (required) |
— |
DropdownMenuLabel, DropdownMenuGroup, DropdownMenuRadioGroup
DropdownMenuLabel must be placed inside DropdownMenuGroup or
DropdownMenuRadioGroup — Base UI wires the group’s aria-labelledby
to it and throws otherwise. DropdownMenuRadioGroup takes
value/onValueChange.
DropdownMenuSub, DropdownMenuSubTrigger, DropdownMenuSubContent
Submenus wrap SubmenuRoot (not a nested root). Positioning is
automatic and RTL-aware — it defaults to side="inline-end" align="start"; don’t override with a hardcoded side="right".
DropdownMenuContent, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuPortal
Styled parts; the shortcut is a plain span for trailing hints.