Installation

pnpm dlx shadcn@latest add @cortexcn/dropdown-menuUsage
import { DropdownMenu, DropdownMenuPortal, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuGroup, DropdownMenuLabel, DropdownMenuItem, DropdownMenuCheckboxItem, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubTrigger, DropdownMenuSubContent } from "@/components/dropdown-menu";Examples
Basic
import { Button } from "@/components/button"import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger } from "@/components/dropdown-menu"export function DropdownMenuBasic() { return ( <div className="flex flex-col gap-6"> <DropdownMenu> <DropdownMenuTrigger asChild> <Button variant="outline" className="w-fit"> Open </Button> </DropdownMenuTrigger> <DropdownMenuContent> <DropdownMenuGroup> <DropdownMenuLabel>My Account</DropdownMenuLabel> <DropdownMenuItem>Profile</DropdownMenuItem> <DropdownMenuItem>Billing</DropdownMenuItem> <DropdownMenuItem>Settings</DropdownMenuItem> </DropdownMenuGroup> <DropdownMenuSeparator /> <DropdownMenuGroup> <DropdownMenuItem>GitHub</DropdownMenuItem> <DropdownMenuItem disabled>API</DropdownMenuItem> <DropdownMenuItem>Support</DropdownMenuItem> </DropdownMenuGroup> </DropdownMenuContent> </DropdownMenu> </div> )}Complex
import * as React from "react"import { Button } from "@/components/button"import { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger } from "@/components/dropdown-menu"import { CreditCardIcon, HelpCircleIcon, LayoutIcon, LogOutIcon, MailIcon, MessageSquareIcon, PanelLeftIcon, PlusCircleIcon, SettingsIcon, UserIcon, UsersIcon } from "lucide-react"export function DropdownMenuComplex() { const [showSidebar, setShowSidebar] = React.useState(true) const [showStatusBar, setShowStatusBar] = React.useState(false) return ( <div className="flex flex-col gap-6"> <DropdownMenu> <DropdownMenuTrigger asChild> <Button variant="outline" className="w-fit"> Complex Menu </Button> </DropdownMenuTrigger> <DropdownMenuContent className="w-56"> <DropdownMenuGroup> <DropdownMenuLabel>My Account</DropdownMenuLabel> <DropdownMenuItem> <UserIcon /> Profile <DropdownMenuShortcut>⇧⌘P</DropdownMenuShortcut> </DropdownMenuItem> <DropdownMenuItem> <CreditCardIcon /> Billing <DropdownMenuShortcut>⌘B</DropdownMenuShortcut> </DropdownMenuItem> <DropdownMenuItem> <SettingsIcon /> Settings <DropdownMenuShortcut>⌘S</DropdownMenuShortcut> </DropdownMenuItem> </DropdownMenuGroup> <DropdownMenuSeparator /> <DropdownMenuGroup> <DropdownMenuLabel>View</DropdownMenuLabel> <DropdownMenuCheckboxItem checked={showSidebar} onCheckedChange={setShowSidebar} > <PanelLeftIcon /> Sidebar </DropdownMenuCheckboxItem> <DropdownMenuCheckboxItem checked={showStatusBar} onCheckedChange={setShowStatusBar} > <LayoutIcon /> Status Bar </DropdownMenuCheckboxItem> </DropdownMenuGroup> <DropdownMenuSeparator /> <DropdownMenuGroup> <DropdownMenuSub> <DropdownMenuSubTrigger> <UsersIcon /> Invite Users </DropdownMenuSubTrigger> <DropdownMenuPortal> <DropdownMenuSubContent> <DropdownMenuGroup> <DropdownMenuItem> <MailIcon /> Email </DropdownMenuItem> <DropdownMenuItem> <MessageSquareIcon /> Message </DropdownMenuItem> </DropdownMenuGroup> <DropdownMenuSeparator /> <DropdownMenuGroup> <DropdownMenuItem> <PlusCircleIcon /> More... </DropdownMenuItem> </DropdownMenuGroup> </DropdownMenuSubContent> </DropdownMenuPortal> </DropdownMenuSub> </DropdownMenuGroup> <DropdownMenuSeparator /> <DropdownMenuGroup> <DropdownMenuItem> <HelpCircleIcon /> Support </DropdownMenuItem> <DropdownMenuItem variant="destructive"> <LogOutIcon /> Sign Out <DropdownMenuShortcut>⇧⌘Q</DropdownMenuShortcut> </DropdownMenuItem> </DropdownMenuGroup> </DropdownMenuContent> </DropdownMenu> </div> )}With icons
import { Button } from "@/components/button"import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger } from "@/components/dropdown-menu"import { CreditCardIcon, LogOutIcon, SettingsIcon, UserIcon } from "lucide-react"export function DropdownMenuWithIcons() { return ( <div className="flex flex-col gap-6"> <DropdownMenu> <DropdownMenuTrigger asChild> <Button variant="outline" className="w-fit"> Open </Button> </DropdownMenuTrigger> <DropdownMenuContent> <DropdownMenuGroup> <DropdownMenuItem> <UserIcon /> Profile </DropdownMenuItem> <DropdownMenuItem> <CreditCardIcon /> Billing </DropdownMenuItem> <DropdownMenuItem> <SettingsIcon /> Settings </DropdownMenuItem> </DropdownMenuGroup> <DropdownMenuSeparator /> <DropdownMenuGroup> <DropdownMenuItem variant="destructive"> <LogOutIcon /> Log out </DropdownMenuItem> </DropdownMenuGroup> </DropdownMenuContent> </DropdownMenu> </div> )}With shortcuts
import { Button } from "@/components/button"import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuTrigger } from "@/components/dropdown-menu"export function DropdownMenuWithShortcuts() { return ( <div className="flex flex-col gap-6"> <DropdownMenu> <DropdownMenuTrigger asChild> <Button variant="outline" className="w-fit"> Open </Button> </DropdownMenuTrigger> <DropdownMenuContent> <DropdownMenuGroup> <DropdownMenuLabel>My Account</DropdownMenuLabel> <DropdownMenuItem> Profile <DropdownMenuShortcut>⇧⌘P</DropdownMenuShortcut> </DropdownMenuItem> <DropdownMenuItem> Billing <DropdownMenuShortcut>⌘B</DropdownMenuShortcut> </DropdownMenuItem> <DropdownMenuItem> Settings <DropdownMenuShortcut>⌘S</DropdownMenuShortcut> </DropdownMenuItem> <DropdownMenuItem> Shortcuts <DropdownMenuShortcut>⌘K</DropdownMenuShortcut> </DropdownMenuItem> </DropdownMenuGroup> <DropdownMenuSeparator /> <DropdownMenuGroup> <DropdownMenuItem> Log out <DropdownMenuShortcut>⇧⌘Q</DropdownMenuShortcut> </DropdownMenuItem> </DropdownMenuGroup> </DropdownMenuContent> </DropdownMenu> </div> )}With submenu
import { Button } from "@/components/button"import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuPortal, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger } from "@/components/dropdown-menu"export function DropdownMenuWithSubmenu() { return ( <div className="flex flex-col gap-6"> <DropdownMenu> <DropdownMenuTrigger asChild> <Button variant="outline" className="w-fit"> Open </Button> </DropdownMenuTrigger> <DropdownMenuContent> <DropdownMenuGroup> <DropdownMenuItem>Team</DropdownMenuItem> <DropdownMenuSub> <DropdownMenuSubTrigger>Invite users</DropdownMenuSubTrigger> <DropdownMenuPortal> <DropdownMenuSubContent> <DropdownMenuGroup> <DropdownMenuItem>Email</DropdownMenuItem> <DropdownMenuItem>Message</DropdownMenuItem> </DropdownMenuGroup> <DropdownMenuSeparator /> <DropdownMenuGroup> <DropdownMenuItem>More...</DropdownMenuItem> </DropdownMenuGroup> </DropdownMenuSubContent> </DropdownMenuPortal> </DropdownMenuSub> <DropdownMenuItem> New Team <DropdownMenuShortcut>⌘+T</DropdownMenuShortcut> </DropdownMenuItem> </DropdownMenuGroup> </DropdownMenuContent> </DropdownMenu> </div> )}With checkboxes
import * as React from "react"import { Button } from "@/components/button"import { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuLabel, DropdownMenuTrigger } from "@/components/dropdown-menu"import { ActivityIcon, LayoutIcon, PanelLeftIcon } from "lucide-react"export function DropdownMenuWithCheckboxes() { const [showStatusBar, setShowStatusBar] = React.useState(true) const [showActivityBar, setShowActivityBar] = React.useState(false) const [showPanel, setShowPanel] = React.useState(false) return ( <div className="flex flex-col gap-6"> <DropdownMenu> <DropdownMenuTrigger asChild> <Button variant="outline" className="w-fit"> Checkboxes </Button> </DropdownMenuTrigger> <DropdownMenuContent className="min-w-40"> <DropdownMenuGroup> <DropdownMenuLabel>Appearance</DropdownMenuLabel> <DropdownMenuCheckboxItem checked={showStatusBar} onCheckedChange={setShowStatusBar} > <LayoutIcon /> Status Bar </DropdownMenuCheckboxItem> <DropdownMenuCheckboxItem checked={showActivityBar} onCheckedChange={setShowActivityBar} disabled > <ActivityIcon /> Activity Bar </DropdownMenuCheckboxItem> <DropdownMenuCheckboxItem checked={showPanel} onCheckedChange={setShowPanel} > <PanelLeftIcon /> Panel </DropdownMenuCheckboxItem> </DropdownMenuGroup> </DropdownMenuContent> </DropdownMenu> </div> )}Checkboxes with icons
import * as React from "react"import { Button } from "@/components/button"import { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuLabel, DropdownMenuTrigger } from "@/components/dropdown-menu"import { BellIcon, MailIcon, MessageSquareIcon } from "lucide-react"export function DropdownMenuWithCheckboxesIcons() { const [notifications, setNotifications] = React.useState({ email: true, sms: false, push: true, }) return ( <div className="flex flex-col gap-6"> <DropdownMenu> <DropdownMenuTrigger asChild> <Button variant="outline" className="w-fit"> Notifications </Button> </DropdownMenuTrigger> <DropdownMenuContent className="min-w-56"> <DropdownMenuGroup> <DropdownMenuLabel>Notification Preferences</DropdownMenuLabel> <DropdownMenuCheckboxItem checked={notifications.email} onCheckedChange={(checked) => setNotifications({ ...notifications, email: checked === true }) } > <MailIcon /> Email notifications </DropdownMenuCheckboxItem> <DropdownMenuCheckboxItem checked={notifications.sms} onCheckedChange={(checked) => setNotifications({ ...notifications, sms: checked === true }) } > <MessageSquareIcon /> SMS notifications </DropdownMenuCheckboxItem> <DropdownMenuCheckboxItem checked={notifications.push} onCheckedChange={(checked) => setNotifications({ ...notifications, push: checked === true }) } > <BellIcon /> Push notifications </DropdownMenuCheckboxItem> </DropdownMenuGroup> </DropdownMenuContent> </DropdownMenu> </div> )}With radio group
import * as React from "react"import { Button } from "@/components/button"import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuTrigger } from "@/components/dropdown-menu"import { ArrowDownIcon, ArrowRightIcon, ArrowUpIcon } from "lucide-react"export function DropdownMenuWithRadio() { const [position, setPosition] = React.useState("bottom") return ( <div className="flex flex-col gap-6"> <DropdownMenu> <DropdownMenuTrigger asChild> <Button variant="outline" className="w-fit"> Radio Group </Button> </DropdownMenuTrigger> <DropdownMenuContent> <DropdownMenuGroup> <DropdownMenuLabel>Panel Position</DropdownMenuLabel> <DropdownMenuRadioGroup value={position} onValueChange={setPosition} > <DropdownMenuRadioItem value="top"> <ArrowUpIcon /> Top </DropdownMenuRadioItem> <DropdownMenuRadioItem value="bottom"> <ArrowDownIcon /> Bottom </DropdownMenuRadioItem> <DropdownMenuRadioItem value="right" disabled> <ArrowRightIcon /> Right </DropdownMenuRadioItem> </DropdownMenuRadioGroup> </DropdownMenuGroup> </DropdownMenuContent> </DropdownMenu> </div> )}Radio with icons
import * as React from "react"import { Button } from "@/components/button"import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuTrigger } from "@/components/dropdown-menu"import { Building2Icon, CreditCardIcon, WalletIcon } from "lucide-react"export function DropdownMenuWithRadioIcons() { const [paymentMethod, setPaymentMethod] = React.useState("card") return ( <div className="flex flex-col gap-6"> <DropdownMenu> <DropdownMenuTrigger asChild> <Button variant="outline">Payment Method</Button> </DropdownMenuTrigger> <DropdownMenuContent className="min-w-56"> <DropdownMenuGroup> <DropdownMenuLabel>Select Payment Method</DropdownMenuLabel> <DropdownMenuRadioGroup value={paymentMethod} onValueChange={setPaymentMethod} > <DropdownMenuRadioItem value="card"> <CreditCardIcon /> Credit Card </DropdownMenuRadioItem> <DropdownMenuRadioItem value="paypal"> <WalletIcon /> PayPal </DropdownMenuRadioItem> <DropdownMenuRadioItem value="bank"> <Building2Icon /> Bank Transfer </DropdownMenuRadioItem> </DropdownMenuRadioGroup> </DropdownMenuGroup> </DropdownMenuContent> </DropdownMenu> </div> )}With destructive items
import { Button } from "@/components/button"import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger } from "@/components/dropdown-menu"import { ArchiveIcon, PencilIcon, ShareIcon, TrashIcon } from "lucide-react"export function DropdownMenuWithDestructive() { return ( <div className="flex flex-col gap-6"> <DropdownMenu> <DropdownMenuTrigger asChild> <Button variant="outline" className="w-fit"> Actions </Button> </DropdownMenuTrigger> <DropdownMenuContent> <DropdownMenuGroup> <DropdownMenuItem> <PencilIcon /> Edit </DropdownMenuItem> <DropdownMenuItem> <ShareIcon /> Share </DropdownMenuItem> </DropdownMenuGroup> <DropdownMenuSeparator /> <DropdownMenuGroup> <DropdownMenuItem> <ArchiveIcon /> Archive </DropdownMenuItem> <DropdownMenuItem variant="destructive"> <TrashIcon /> Delete </DropdownMenuItem> </DropdownMenuGroup> </DropdownMenuContent> </DropdownMenu> </div> )}With avatar
import { Avatar, AvatarFallback, AvatarImage } from "@/components/avatar"import { Button } from "@/components/button"import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger } from "@/components/dropdown-menu"import { BadgeCheckIcon, BellIcon, ChevronsUpDownIcon, CreditCardIcon, LogOutIcon } from "lucide-react"export function DropdownMenuWithAvatar() { const menuContent = ( <> <DropdownMenuGroup> <DropdownMenuItem> <BadgeCheckIcon /> Account </DropdownMenuItem> <DropdownMenuItem> <CreditCardIcon /> Billing </DropdownMenuItem> <DropdownMenuItem> <BellIcon /> Notifications </DropdownMenuItem> </DropdownMenuGroup> <DropdownMenuSeparator /> <DropdownMenuGroup> <DropdownMenuItem> <LogOutIcon /> Sign Out </DropdownMenuItem> </DropdownMenuGroup> </> ) return ( <div className="flex flex-col gap-6"> <div className="flex items-center justify-between gap-4"> <DropdownMenu> <DropdownMenuTrigger asChild> <Button variant="outline" className="h-12 justify-start px-2 md:max-w-[200px] style-sera:font-normal style-sera:tracking-normal style-sera:normal-case" > <Avatar> <AvatarImage src="https://github.com/shadcn.png" alt="Shadcn" /> <AvatarFallback className="rounded-lg">CN</AvatarFallback> </Avatar> <div className="grid flex-1 text-left text-sm leading-tight"> <span className="truncate font-semibold">shadcn</span> <span className="truncate text-xs text-muted-foreground"> shadcn@example.com </span> </div> <ChevronsUpDownIcon className="ml-auto text-muted-foreground" /> </Button> </DropdownMenuTrigger> <DropdownMenuContent className="w-(--radix-dropdown-menu-trigger-width) min-w-56"> {menuContent} </DropdownMenuContent> </DropdownMenu> <DropdownMenu> <DropdownMenuTrigger asChild> <Button variant="ghost" size="icon" className="rounded-full"> <Avatar> <AvatarImage src="https://github.com/shadcn.png" alt="shadcn" /> <AvatarFallback>LR</AvatarFallback> </Avatar> </Button> </DropdownMenuTrigger> <DropdownMenuContent align="end" side="top"> {menuContent} </DropdownMenuContent> </DropdownMenu> </div> </div> )}In dialog
import { Button } from "@/components/button"import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger } from "@/components/dialog"import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuPortal, DropdownMenuSeparator, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger } from "@/components/dropdown-menu"import { ClipboardPasteIcon, CopyIcon, ScissorsIcon, TrashIcon } from "lucide-react"export function DropdownMenuInDialog() { return ( <div className="flex flex-col gap-6"> <Dialog> <DialogTrigger asChild> <Button variant="outline">Open Dialog</Button> </DialogTrigger> <DialogContent> <DialogHeader> <DialogTitle>Dropdown Menu Example</DialogTitle> <DialogDescription> Click the button below to see the dropdown menu. </DialogDescription> </DialogHeader> <DropdownMenu> <DropdownMenuTrigger asChild> <Button variant="outline" className="w-fit"> Open Menu </Button> </DropdownMenuTrigger> <DropdownMenuContent> <DropdownMenuGroup> <DropdownMenuItem> <CopyIcon /> Copy </DropdownMenuItem> <DropdownMenuItem> <ScissorsIcon /> Cut </DropdownMenuItem> <DropdownMenuItem> <ClipboardPasteIcon /> Paste </DropdownMenuItem> </DropdownMenuGroup> <DropdownMenuSeparator /> <DropdownMenuSub> <DropdownMenuSubTrigger>More Options</DropdownMenuSubTrigger> <DropdownMenuPortal> <DropdownMenuSubContent> <DropdownMenuGroup> <DropdownMenuItem>Save Page...</DropdownMenuItem> <DropdownMenuItem>Create Shortcut...</DropdownMenuItem> <DropdownMenuItem>Name Window...</DropdownMenuItem> </DropdownMenuGroup> <DropdownMenuSeparator /> <DropdownMenuGroup> <DropdownMenuItem>Developer Tools</DropdownMenuItem> </DropdownMenuGroup> </DropdownMenuSubContent> </DropdownMenuPortal> </DropdownMenuSub> <DropdownMenuSeparator /> <DropdownMenuGroup> <DropdownMenuItem variant="destructive"> <TrashIcon /> Delete </DropdownMenuItem> </DropdownMenuGroup> </DropdownMenuContent> </DropdownMenu> </DialogContent> </Dialog> </div> )}With inset
import * as React from "react"import { Button } from "@/components/button"import { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger } from "@/components/dropdown-menu"import { CopyIcon, ScissorsIcon } from "lucide-react"export function DropdownMenuWithInset() { const [showBookmarks, setShowBookmarks] = React.useState(true) const [showUrls, setShowUrls] = React.useState(false) const [theme, setTheme] = React.useState("system") return ( <div className="flex flex-col gap-6"> <DropdownMenu> <DropdownMenuTrigger asChild> <Button variant="outline" className="w-fit"> Open </Button> </DropdownMenuTrigger> <DropdownMenuContent className="w-44"> <DropdownMenuGroup> <DropdownMenuLabel>Actions</DropdownMenuLabel> <DropdownMenuItem> <CopyIcon /> Copy </DropdownMenuItem> <DropdownMenuItem> <ScissorsIcon /> Cut </DropdownMenuItem> <DropdownMenuItem inset>Paste</DropdownMenuItem> </DropdownMenuGroup> <DropdownMenuSeparator /> <DropdownMenuGroup> <DropdownMenuLabel inset>Appearance</DropdownMenuLabel> <DropdownMenuCheckboxItem inset checked={showBookmarks} onCheckedChange={setShowBookmarks} > Bookmarks </DropdownMenuCheckboxItem> <DropdownMenuCheckboxItem inset checked={showUrls} onCheckedChange={setShowUrls} > Full URLs </DropdownMenuCheckboxItem> </DropdownMenuGroup> <DropdownMenuSeparator /> <DropdownMenuGroup> <DropdownMenuLabel inset>Theme</DropdownMenuLabel> <DropdownMenuRadioGroup value={theme} onValueChange={setTheme}> <DropdownMenuRadioItem inset value="light"> Light </DropdownMenuRadioItem> <DropdownMenuRadioItem inset value="dark"> Dark </DropdownMenuRadioItem> <DropdownMenuRadioItem inset value="system"> System </DropdownMenuRadioItem> </DropdownMenuRadioGroup> </DropdownMenuGroup> <DropdownMenuSeparator /> <DropdownMenuSub> <DropdownMenuSubTrigger inset>More Options</DropdownMenuSubTrigger> <DropdownMenuPortal> <DropdownMenuSubContent> <DropdownMenuGroup> <DropdownMenuItem>Save Page...</DropdownMenuItem> <DropdownMenuItem>Create Shortcut...</DropdownMenuItem> </DropdownMenuGroup> </DropdownMenuSubContent> </DropdownMenuPortal> </DropdownMenuSub> </DropdownMenuContent> </DropdownMenu> </div> )}Adapted from the shadcn/ui Dropdown Menu (MIT).
