Dropdown Menu
A dropdown menu component for displaying contextual actions, navigation items, and options with support for nested menus, checkboxes, radio groups, and keyboard navigation.
Usage
Basic Dropdown Menu
A simple dropdown menu with action items:
import {
DropdownMenu,
DropdownMenuTrigger,
DropdownMenuContent,
DropdownMenuItem,
} from "@prisma-docs/ui/components/dropdown-menu";
export function BasicDropdown() {
return (
<DropdownMenu>
<DropdownMenuTrigger className="px-3 py-1.5 text-sm font-normal border border-fd-border rounded-low bg-background-default hover:bg-background-neutral text-foreground-neutral disabled:text-foreground-neutral-weaker active:hover:font-medium active:font-medium shadow-box outline-none">
Open Menu
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem>Profile</DropdownMenuItem>
<DropdownMenuItem>Settings</DropdownMenuItem>
<DropdownMenuItem>Logout</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
}Live Example:
With Icons
Add icons to menu items for better visual hierarchy:
import {
DropdownMenu,
DropdownMenuTrigger,
DropdownMenuContent,
DropdownMenuItem,
} from "@prisma-docs/ui/components/dropdown-menu";
import { User, Settings, LogOut } from "lucide-react";
export function DropdownWithIcons() {
return (
<DropdownMenu>
<DropdownMenuTrigger className="px-3 py-1.5 text-sm font-normal border border-fd-border rounded-low bg-background-default hover:bg-background-neutral text-foreground-neutral disabled:text-foreground-neutral-weaker active:hover:font-medium active:font-medium shadow-box outline-none">
Account
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem>
<User />
Profile
</DropdownMenuItem>
<DropdownMenuItem>
<Settings />
Settings
</DropdownMenuItem>
<DropdownMenuItem>
<LogOut />
Logout
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
}Live Example:
With Labels and Separators
Organize menu items with labels and separators:
import {
DropdownMenu,
DropdownMenuTrigger,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
} from "@prisma-docs/ui/components/dropdown-menu";
import { User, Settings, Mail, MessageSquare, LogOut } from "lucide-react";
export function OrganizedDropdown() {
return (
<DropdownMenu>
<DropdownMenuTrigger className="px-3 py-1.5 text-sm font-normal border border-fd-border rounded-low bg-background-default hover:bg-background-neutral text-foreground-neutral disabled:text-foreground-neutral-weaker active:hover:font-medium active:font-medium shadow-box outline-none">
Menu
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuGroup>
<DropdownMenuLabel>My Account</DropdownMenuLabel>
</DropdownMenuGroup>
<DropdownMenuSeparator />
<DropdownMenuItem>
<User />
Profile
</DropdownMenuItem>
<DropdownMenuItem>
<Settings />
Settings
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuGroup>
<DropdownMenuLabel>Communication</DropdownMenuLabel>
</DropdownMenuGroup>
<DropdownMenuItem>
<Mail />
Email
</DropdownMenuItem>
<DropdownMenuItem>
<MessageSquare />
Messages
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem>
<LogOut />
Logout
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
}Live Example:
With Checkbox Items
Add checkbox items for toggleable options:
import {
DropdownMenu,
DropdownMenuTrigger,
DropdownMenuContent,
DropdownMenuCheckboxItem,
DropdownMenuLabel,
DropdownMenuSeparator,
} from "@prisma-docs/ui/components/dropdown-menu";
import { useState } from "react";
export function CheckboxDropdown() {
const [showStatusBar, setShowStatusBar] = useState(true);
const [showActivityBar, setShowActivityBar] = useState(false);
const [showPanel, setShowPanel] = useState(false);
return (
<DropdownMenu>
<DropdownMenuTrigger className="px-3 py-1.5 text-sm font-normal border border-fd-border rounded-low bg-background-default hover:bg-background-neutral text-foreground-neutral disabled:text-foreground-neutral-weaker active:hover:font-medium active:font-medium shadow-box outline-none">
View Options
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuGroup>
<DropdownMenuLabel>Appearance</DropdownMenuLabel>
</DropdownMenuGroup>
<DropdownMenuSeparator />
<DropdownMenuCheckboxItem
checked={showStatusBar}
onCheckedChange={setShowStatusBar}
>
Status Bar
</DropdownMenuCheckboxItem>
<DropdownMenuCheckboxItem
checked={showActivityBar}
onCheckedChange={setShowActivityBar}
>
Activity Bar
</DropdownMenuCheckboxItem>
<DropdownMenuCheckboxItem
checked={showPanel}
onCheckedChange={setShowPanel}
>
Panel
</DropdownMenuCheckboxItem>
</DropdownMenuContent>
</DropdownMenu>
);
}Live Example:
With Radio Groups
Use radio groups for mutually exclusive options:
import {
DropdownMenu,
DropdownMenuTrigger,
DropdownMenuContent,
DropdownMenuRadioGroup,
DropdownMenuRadioItem,
DropdownMenuLabel,
DropdownMenuSeparator,
} from "@prisma-docs/ui/components/dropdown-menu";
import { useState } from "react";
export function RadioDropdown() {
const [position, setPosition] = useState("bottom");
return (
<DropdownMenu>
<DropdownMenuTrigger className="px-3 py-1.5 text-sm font-normal border border-fd-border rounded-low bg-background-default hover:bg-background-neutral text-foreground-neutral disabled:text-foreground-neutral-weaker active:hover:font-medium active:font-medium shadow-box outline-none">
Panel Position
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuGroup>
<DropdownMenuLabel>Position</DropdownMenuLabel>
</DropdownMenuGroup>
<DropdownMenuSeparator />
<DropdownMenuRadioGroup value={position} onValueChange={setPosition}>
<DropdownMenuRadioItem value="top">Top</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="bottom">Bottom</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="right">Right</DropdownMenuRadioItem>
</DropdownMenuRadioGroup>
</DropdownMenuContent>
</DropdownMenu>
);
}Live Example:
With Nested Submenus
Create nested dropdown menus for hierarchical navigation:
import {
DropdownMenu,
DropdownMenuTrigger,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuSub,
DropdownMenuSubTrigger,
DropdownMenuSubContent,
} from "@prisma-docs/ui/components/dropdown-menu";
import { Plus, User, Mail } from "lucide-react";
export function NestedDropdown() {
return (
<DropdownMenu>
<DropdownMenuTrigger className="px-3 py-1.5 text-sm font-normal border border-fd-border rounded-low bg-background-default hover:bg-background-neutral text-foreground-neutral disabled:text-foreground-neutral-weaker active:hover:font-medium active:font-medium shadow-box outline-none">
Actions
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem>
<User />
Profile
</DropdownMenuItem>
<DropdownMenuSub>
<DropdownMenuSubTrigger>
<Plus />
New
</DropdownMenuSubTrigger>
<DropdownMenuSubContent>
<DropdownMenuItem>Project</DropdownMenuItem>
<DropdownMenuItem>Repository</DropdownMenuItem>
<DropdownMenuItem>Team</DropdownMenuItem>
</DropdownMenuSubContent>
</DropdownMenuSub>
<DropdownMenuItem>
<Mail />
Invite
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
}Live Example:
With Keyboard Shortcuts
Display keyboard shortcuts for quick reference:
import {
DropdownMenu,
DropdownMenuTrigger,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuShortcut,
} from "@prisma-docs/ui/components/dropdown-menu";
export function ShortcutDropdown() {
return (
<DropdownMenu>
<DropdownMenuTrigger className="px-3 py-1.5 text-sm font-normal border border-fd-border rounded-low bg-background-default hover:bg-background-neutral text-foreground-neutral disabled:text-foreground-neutral-weaker active:hover:font-medium active:font-medium shadow-box outline-none">
Edit
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem>
Undo
<DropdownMenuShortcut>⌘Z</DropdownMenuShortcut>
</DropdownMenuItem>
<DropdownMenuItem>
Redo
<DropdownMenuShortcut>⌘⇧Z</DropdownMenuShortcut>
</DropdownMenuItem>
<DropdownMenuItem>
Cut
<DropdownMenuShortcut>⌘X</DropdownMenuShortcut>
</DropdownMenuItem>
<DropdownMenuItem>
Copy
<DropdownMenuShortcut>⌘C</DropdownMenuShortcut>
</DropdownMenuItem>
<DropdownMenuItem>
Paste
<DropdownMenuShortcut>⌘V</DropdownMenuShortcut>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
}Live Example:
Destructive Actions
Highlight destructive actions with the variant prop:
import {
DropdownMenu,
DropdownMenuTrigger,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuSeparator,
} from "@prisma-docs/ui/components/dropdown-menu";
import { Settings, Trash } from "lucide-react";
export function DestructiveDropdown() {
return (
<DropdownMenu>
<DropdownMenuTrigger className="px-3 py-1.5 text-sm font-normal border border-fd-border rounded-low bg-background-default hover:bg-background-neutral text-foreground-neutral disabled:text-foreground-neutral-weaker active:hover:font-medium active:font-medium shadow-box outline-none">
Options
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem>
<Settings />
Settings
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem variant="destructive">
<Trash />
Delete
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
}Live Example:
Positioning
Control the menu position with align and side props:
import {
DropdownMenu,
DropdownMenuTrigger,
DropdownMenuContent,
DropdownMenuItem,
} from "@prisma-docs/ui/components/dropdown-menu";
export function PositionedDropdown() {
return (
<DropdownMenu>
<DropdownMenuTrigger className="px-3 py-1.5 text-sm font-normal border border-fd-border rounded-low bg-background-default hover:bg-background-neutral text-foreground-neutral disabled:text-foreground-neutral-weaker active:hover:font-medium active:font-medium shadow-box outline-none">
Positioned Menu
</DropdownMenuTrigger>
<DropdownMenuContent align="end" side="top">
<DropdownMenuItem>Item 1</DropdownMenuItem>
<DropdownMenuItem>Item 2</DropdownMenuItem>
<DropdownMenuItem>Item 3</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
}Live Example:
API Reference
DropdownMenu
The root component that wraps the entire dropdown menu.
open- Control the open state (boolean, optional)onOpenChange- Callback when open state changes ((open: boolean) => void, optional)defaultOpen- Default open state (boolean, optional)modal- Whether to render in a modal (boolean, default: true)
DropdownMenuTrigger
The button that toggles the dropdown menu.
asChild- Merge props with child component (boolean, optional)disabled- Disable the trigger (boolean, optional)
DropdownMenuContent
The container for dropdown menu items.
align- Alignment relative to trigger:"start"|"center"|"end"(default: "start")side- Side to display menu:"top"|"right"|"bottom"|"left"(default: "bottom")alignOffset- Offset in pixels from aligned position (number, default: 0)sideOffset- Offset in pixels from side (number, default: 4)className- Additional CSS classes (string, optional)
DropdownMenuItem
An individual menu item.
inset- Add left padding for alignment (boolean, optional)variant- Visual style:"default"|"destructive"(default: "default")disabled- Disable the item (boolean, optional)onSelect- Callback when item is selected ((event: Event) => void, optional)className- Additional CSS classes (string, optional)
DropdownMenuCheckboxItem
A checkbox menu item.
checked- Checked state (boolean | "indeterminate", optional)onCheckedChange- Callback when checked state changes ((checked: boolean) => void, optional)disabled- Disable the item (boolean, optional)className- Additional CSS classes (string, optional)
DropdownMenuRadioGroup
Container for radio items.
value- Selected value (string, optional)onValueChange- Callback when value changes ((value: string) => void, optional)
DropdownMenuRadioItem
A radio menu item.
value- The value for this item (string, required)disabled- Disable the item (boolean, optional)className- Additional CSS classes (string, optional)
DropdownMenuLabel
A label for grouping menu items.
inset- Add left padding for alignment (boolean, optional)className- Additional CSS classes (string, optional)
DropdownMenuSeparator
A visual separator between menu items.
className- Additional CSS classes (string, optional)
DropdownMenuShortcut
Display keyboard shortcuts.
className- Additional CSS classes (string, optional)
DropdownMenuSub
Container for nested submenus.
open- Control submenu open state (boolean, optional)onOpenChange- Callback when submenu open state changes ((open: boolean) => void, optional)
DropdownMenuSubTrigger
Trigger for opening a submenu.
inset- Add left padding for alignment (boolean, optional)disabled- Disable the trigger (boolean, optional)className- Additional CSS classes (string, optional)
DropdownMenuSubContent
Container for submenu items.
- All props from
DropdownMenuContent
Features
- ✅ Full keyboard navigation support
- ✅ Supports nested submenus
- ✅ Checkbox and radio group items
- ✅ Customizable positioning (align, side, offset)
- ✅ Keyboard shortcuts display
- ✅ Disabled state support
- ✅ Destructive action styling
- ✅ Smooth animations
- ✅ Accessible (ARIA compliant)
- ✅ Based on Base UI Menu primitives
Best Practices
- Use clear, action-oriented labels for menu items
- Group related items together with labels and separators
- Place destructive actions at the bottom, separated from other items
- Limit menu depth to 2 levels (avoid deeply nested submenus)
- Use icons consistently throughout the menu
- Show keyboard shortcuts for frequently used actions
- Use
asChildprop on trigger to merge with custom buttons - Keep menu items concise (1-2 words when possible)
- Use radio groups for mutually exclusive options
- Use checkboxes for toggleable settings
- Disable items that are temporarily unavailable rather than hiding them
Accessibility
- Automatically manages focus
- Supports keyboard navigation (Arrow keys, Enter, Space, Escape)
- ARIA attributes included
- Screen reader friendly
- Focus trapping within open menu
- Escape key closes menu
- Click outside closes menu
Common Use Cases
The DropdownMenu component is perfect for:
- User account menus - Profile, settings, logout actions
- Context menus - Right-click actions on items
- More actions menus - Additional options that don't fit in the main UI
- Settings toggles - Quick access to view or preference settings
- Navigation menus - Mobile navigation or compact menu bars
- Filtering options - Quick filters with checkbox items
- Selection controls - Radio groups for mutually exclusive choices
- Command palettes - Quick actions with keyboard shortcuts