apps/eclipse/content/design-system/components/dropdownmenu.mdx
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuCheckboxItem, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuGroup, DropdownMenuSub, DropdownMenuSubTrigger, DropdownMenuSubContent, } from "@prisma/eclipse"; import { ChevronDown, User, Settings, LogOut, Mail, MessageSquare, Plus, Trash } from "lucide-react"; import { CheckboxDropdownExample, RadioDropdownExample } from "@/components/dropdown-examples/interactive-examples";
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>
);
}
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>
);
}
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>
);
}
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>
);
}
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>
);
}
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>
);
}
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>
);
}
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>
);
}
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>
);
}
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)The button that toggles the dropdown menu.
asChild - Merge props with child component (boolean, optional)disabled - Disable the trigger (boolean, optional)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)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)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)Container for radio items.
value - Selected value (string, optional)onValueChange - Callback when value changes ((value: string) => void, optional)A radio menu item.
value - The value for this item (string, required)disabled - Disable the item (boolean, optional)className - Additional CSS classes (string, optional)A label for grouping menu items.
inset - Add left padding for alignment (boolean, optional)className - Additional CSS classes (string, optional)A visual separator between menu items.
className - Additional CSS classes (string, optional)Display keyboard shortcuts.
className - Additional CSS classes (string, optional)Container for nested submenus.
open - Control submenu open state (boolean, optional)onOpenChange - Callback when submenu open state changes ((open: boolean) => void, optional)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)Container for submenu items.
DropdownMenuContentasChild prop on trigger to merge with custom buttonsThe DropdownMenu component is perfect for: