Dropdown Menu
Dropdown menus display a list of actions or options that a user can choose from, triggered by a button.
Overview
The DropdownMenu component provides a floating menu of actions triggered by a button click. Built on Base UI Menu, it supports keyboard navigation, submenus, checkbox items, radio items, and accessible labelling.
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@rogo-technologies/ui/dropdown-menu"
<DropdownMenu>
<DropdownMenuTrigger>
<button>Open</button>
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem>Action One</DropdownMenuItem>
<DropdownMenuItem>Action Two</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>Basic
A standard dropdown with labeled groups, items, keyboard shortcuts, and a separator.
<DropdownMenu>
<DropdownMenuTrigger>
<button>Open Menu</button>
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuLabel>My Account</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuItem>
Profile
<DropdownMenuShortcut>⇧⌘P</DropdownMenuShortcut>
</DropdownMenuItem>
<DropdownMenuItem>
Settings
<DropdownMenuShortcut>⌘S</DropdownMenuShortcut>
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem>Log out</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>Checkbox Items
Use DropdownMenuCheckboxItem for toggling boolean options. Each item manages its own checked / onCheckedChange state.
const [showStatusBar, setShowStatusBar] = useState(true)
const [showPanel, setShowPanel] = useState(false)
<DropdownMenu>
<DropdownMenuTrigger>
<button>View Options</button>
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuLabel>Appearance</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuCheckboxItem
checked={showStatusBar}
onCheckedChange={setShowStatusBar}
>
Status Bar
</DropdownMenuCheckboxItem>
<DropdownMenuCheckboxItem
checked={showPanel}
onCheckedChange={setShowPanel}
>
Panel
</DropdownMenuCheckboxItem>
</DropdownMenuContent>
</DropdownMenu>Radio Items
Use DropdownMenuRadioGroup and DropdownMenuRadioItem for single-select options within a menu. The selected item shows a checkmark indicator.
const [sort, setSort] = useState("relevance")
<DropdownMenu>
<DropdownMenuTrigger>
<button>Sort By: {sort}</button>
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuLabel>Sort order</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuRadioGroup value={sort} onValueChange={setSort}>
<DropdownMenuRadioItem value="relevance">Relevance</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="date">Date</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="name">Name</DropdownMenuRadioItem>
</DropdownMenuRadioGroup>
</DropdownMenuContent>
</DropdownMenu>Submenus
Use DropdownMenuSub, DropdownMenuSubTrigger, and DropdownMenuSubContent to nest menus. A chevron icon is automatically appended to the sub-trigger.
<DropdownMenu>
<DropdownMenuTrigger>
<button>Actions</button>
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem>New File</DropdownMenuItem>
<DropdownMenuSub>
<DropdownMenuSubTrigger>Share</DropdownMenuSubTrigger>
<DropdownMenuSubContent>
<DropdownMenuItem>Email</DropdownMenuItem>
<DropdownMenuItem>Slack</DropdownMenuItem>
<DropdownMenuItem>Copy Link</DropdownMenuItem>
</DropdownMenuSubContent>
</DropdownMenuSub>
<DropdownMenuSeparator />
<DropdownMenuItem>Download</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>Destructive Items
Use actionType="destructive" on a DropdownMenuItem to indicate a destructive action. The item text turns red on hover.
<DropdownMenuItem actionType="destructive">Delete</DropdownMenuItem>Groups and Labels
Use DropdownMenuGroup and DropdownMenuLabel to organize related items into sections.
<DropdownMenuContent>
<DropdownMenuGroup>
<DropdownMenuLabel>Navigation</DropdownMenuLabel>
<DropdownMenuItem>Dashboard</DropdownMenuItem>
<DropdownMenuItem>Analytics</DropdownMenuItem>
</DropdownMenuGroup>
<DropdownMenuSeparator />
<DropdownMenuGroup>
<DropdownMenuLabel>Settings</DropdownMenuLabel>
<DropdownMenuItem>Account</DropdownMenuItem>
<DropdownMenuItem disabled>Billing (coming soon)</DropdownMenuItem>
</DropdownMenuGroup>
</DropdownMenuContent>Trigger with asChild
Use asChild on DropdownMenuTrigger to render the trigger as a custom element instead of the default button.
import { Button } from "@rogo-technologies/ui/button"
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost">Options</Button>
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem>Edit</DropdownMenuItem>
<DropdownMenuItem>Delete</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>Positioning
Use side, align, sideOffset, and alignOffset on DropdownMenuContent to control the popup placement relative to the trigger.
// Opens to the right, aligned to the top
<DropdownMenuContent side="right" align="start" sideOffset={8}>
...
</DropdownMenuContent>
// Opens above, centered
<DropdownMenuContent side="top" align="center">
...
</DropdownMenuContent>Props
DropdownMenu
The root component that manages open state.
| Prop | Type | Default | Description |
|---|---|---|---|
open | boolean | — | Controlled open state. |
defaultOpen | boolean | false | Initial open state for uncontrolled usage. |
onOpenChange | (open: boolean) => void | — | Callback when open state changes. |
DropdownMenuTrigger
The button that toggles the menu open/closed.
| Prop | Type | Default | Description |
|---|---|---|---|
asChild | boolean | false | Render as the child element instead of a button. |
DropdownMenuContent
Convenience wrapper that renders Portal → Positioner → Popup.
| Prop | Type | Default | Description |
|---|---|---|---|
side | "top" | "right" | "bottom" | "left" | "bottom" | Side of the trigger to anchor. |
sideOffset | number | 4 | Offset from the trigger edge in px. |
align | "start" | "center" | "end" | "start" | Alignment along the side axis. |
alignOffset | number | — | Offset from the alignment edge. |
collisionPadding | number | Padding | — | Padding from viewport edges for collision detection. |
positionerClassName | string | — | Additional class for the positioner wrapper. |
DropdownMenuItem
A menu item that triggers an action.
| Prop | Type | Default | Description |
|---|---|---|---|
inset | boolean | false | Adds left padding to align with items that have icons. |
actionType | "default" | "destructive" | "default" | Visual style — destructive shows red text. |
onSelect | (event: MouseEvent) => void | — | Callback when selected (mapped to onClick). |
disabled | boolean | false | Disables the item. |
DropdownMenuCheckboxItem
A menu item with a checkbox indicator.
| Prop | Type | Default | Description |
|---|---|---|---|
checked | boolean | — | Controlled checked state. |
onCheckedChange | (checked: boolean) => void | — | Callback when checked state changes. |
DropdownMenuRadioGroup
Wraps radio items for single selection.
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | — | Controlled selected value. |
onValueChange | (value: string) => void | — | Callback when selection changes. |
DropdownMenuRadioItem
A radio item within a radio group. Shows a checkmark when selected.
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | — | Unique value identifying this item. |
DropdownMenuSubTrigger
The item that opens a submenu. Automatically includes a chevron icon.
| Prop | Type | Default | Description |
|---|---|---|---|
inset | boolean | false | Adds left padding for alignment. |
DropdownMenuSubContent
The popup content for a submenu.
| Prop | Type | Default | Description |
|---|---|---|---|
side | "top" | "right" | "bottom" | "left" | "right" | Side relative to the sub-trigger. |
sideOffset | number | -4 | Offset from the sub-trigger edge. |
align | "start" | "center" | "end" | "start" | Alignment along the side axis. |
DropdownMenuLabel
A non-interactive label for a group of items.
| Prop | Type | Default | Description |
|---|---|---|---|
inset | boolean | false | Adds left padding for alignment. |
DropdownMenuSeparator
A visual divider between groups of items.
DropdownMenuShortcut
Displays a keyboard shortcut hint, right-aligned within a menu item.
Accessibility
- Menu uses
role="menu"withrole="menuitem"children - Full keyboard navigation:
↑/↓to move,Enter/Spaceto select,Escto close - Submenus open with
→and close with← - Focus is trapped within the menu while open
- Menu closes when clicking outside or pressing
Escape - Checkbox items use
role="menuitemcheckbox" - Radio items use
role="menuitemradio"within arole="group"
// Accessible labelling
<DropdownMenu>
<DropdownMenuTrigger aria-label="More actions">
<button>⋯</button>
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem>Edit</DropdownMenuItem>
<DropdownMenuItem>Delete</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>Usage Guidelines
Do
- Use dropdown menus for contextual actions related to a specific element
- Group related items with labels and separators
- Place destructive actions last, separated visually
- Keep menu items concise — use short, action-oriented labels
- Use radio items for single-select options (e.g. sort order, view mode)
- Use checkbox items for toggling independent boolean settings
Don't
- Don't use dropdown menus for navigation — use a navigation component instead
- Don't nest submenus more than one level deep — it becomes difficult to use
- Don't place too many items in a single menu — consider grouping or using a dialog
- Don't use dropdown menus for form inputs — use select, combobox, or radio groups instead
- Don't forget to add keyboard shortcuts for frequently used actions