Dropdown Menu
Usage
Add the theme to your CSS:
@import "tailwindcss";
@import "@danielfrg/solid-ui-nova/theme.css";
Import and use the Dropdown Menu components:
import {
DropdownMenu,
DropdownMenuTrigger,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuSeparator,
} from "@danielfrg/solid-ui-nova/dropdown-menu"
;<DropdownMenu>
<DropdownMenuTrigger>Open</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem>Profile</DropdownMenuItem>
<DropdownMenuItem>Settings</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem>Log out</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
Demo
Source
import { createSignal } from "solid-js"
import {
DropdownMenu,
DropdownMenuCheckboxItem,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuPortal,
DropdownMenuRadioGroup,
DropdownMenuRadioItem,
DropdownMenuSeparator,
DropdownMenuShortcut,
DropdownMenuSub,
DropdownMenuSubContent,
DropdownMenuSubTrigger,
DropdownMenuTrigger,
} from "@danielfrg/solid-ui-nova/dropdown-menu"
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@danielfrg/solid-ui-nova/dialog"
import { Avatar, AvatarFallback, AvatarImage } from "@danielfrg/solid-ui-nova/avatar"
import { Button, buttonVariants } from "@danielfrg/solid-ui-nova/button"
import {
Activity,
Archive,
ArrowDown,
ArrowRight,
ArrowUp,
BadgeCheck,
Bell,
Building2,
ChevronsUpDown,
Clipboard,
Copy,
CreditCard,
Eye,
File,
FileCode,
Folder,
FolderOpen,
FolderSearch,
Layout,
LogOut,
Mail,
MessageSquare,
Moon,
Monitor,
MoreHorizontal,
Palette,
PanelLeft,
Pencil,
Save,
Scissors,
Settings,
Share,
Sun,
Trash,
User,
Wallet,
} from "lucide-solid"
import { ExampleWrapper, Example } from "@/components/example"
export default function DropdownMenuExample() {
return (
<ExampleWrapper>
<DropdownMenuBasic />
<DropdownMenuComplex />
<DropdownMenuSides />
<DropdownMenuWithIcons />
<DropdownMenuWithShortcuts />
<DropdownMenuWithSubmenu />
<DropdownMenuWithCheckboxes />
<DropdownMenuWithCheckboxesIcons />
<DropdownMenuWithRadio />
<DropdownMenuWithRadioIcons />
<DropdownMenuWithDestructive />
<DropdownMenuWithAvatar />
<DropdownMenuInDialog />
<DropdownMenuWithInset />
</ExampleWrapper>
)
}
function DropdownMenuBasic() {
return (
<Example title="Basic" class="items-center">
<DropdownMenu>
<DropdownMenuTrigger class={buttonVariants({ variant: "outline" }) + " w-fit"}>Open</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuGroup>
<DropdownMenuLabel>My Account</DropdownMenuLabel>
<DropdownMenuItem>Profile</DropdownMenuItem>
<DropdownMenuItem>Billing</DropdownMenuItem>
<DropdownMenuItem>Settings</DropdownMenuItem>
</DropdownMenuGroup>
<DropdownMenuSeparator />
<DropdownMenuItem>GitHub</DropdownMenuItem>
<DropdownMenuItem>Support</DropdownMenuItem>
<DropdownMenuItem disabled>API</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</Example>
)
}
function DropdownMenuSides() {
const placements = ["top", "right", "bottom", "left"] as const
return (
<Example title="Sides">
<div class="flex flex-wrap justify-center gap-2">
{placements.map((placement) => (
<DropdownMenu placement={placement}>
<DropdownMenuTrigger class={buttonVariants({ variant: "outline" }) + " w-fit capitalize"}>
{placement}
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuGroup>
<DropdownMenuItem>Profile</DropdownMenuItem>
<DropdownMenuItem>Billing</DropdownMenuItem>
<DropdownMenuItem>Settings</DropdownMenuItem>
</DropdownMenuGroup>
</DropdownMenuContent>
</DropdownMenu>
))}
</div>
</Example>
)
}
function DropdownMenuWithIcons() {
return (
<Example title="With Icons" class="items-center">
<DropdownMenu>
<DropdownMenuTrigger class={buttonVariants({ variant: "outline" }) + " w-fit"}>Open</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem>
<User />
Profile
</DropdownMenuItem>
<DropdownMenuItem>
<CreditCard />
Billing
</DropdownMenuItem>
<DropdownMenuItem>
<Settings />
Settings
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem variant="destructive">
<LogOut />
Log out
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</Example>
)
}
function DropdownMenuWithShortcuts() {
return (
<Example title="With Shortcuts" class="items-center">
<DropdownMenu>
<DropdownMenuTrigger class={buttonVariants({ variant: "outline" }) + " w-fit"}>Open</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>
Keyboard shortcuts
<DropdownMenuShortcut>⌘K</DropdownMenuShortcut>
</DropdownMenuItem>
</DropdownMenuGroup>
<DropdownMenuSeparator />
<DropdownMenuItem>
Log out
<DropdownMenuShortcut>⇧⌘Q</DropdownMenuShortcut>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</Example>
)
}
function DropdownMenuWithSubmenu() {
return (
<Example title="With Submenu" class="items-center">
<DropdownMenu>
<DropdownMenuTrigger class={buttonVariants({ variant: "outline" }) + " w-fit"}>Open</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuGroup>
<DropdownMenuItem>Team</DropdownMenuItem>
<DropdownMenuSub>
<DropdownMenuSubTrigger>Invite users</DropdownMenuSubTrigger>
<DropdownMenuPortal>
<DropdownMenuSubContent>
<DropdownMenuItem>Email</DropdownMenuItem>
<DropdownMenuItem>Message</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem>More...</DropdownMenuItem>
</DropdownMenuSubContent>
</DropdownMenuPortal>
</DropdownMenuSub>
<DropdownMenuItem>
New Team
<DropdownMenuShortcut>⌘+T</DropdownMenuShortcut>
</DropdownMenuItem>
</DropdownMenuGroup>
</DropdownMenuContent>
</DropdownMenu>
</Example>
)
}
function DropdownMenuWithCheckboxes() {
const [showStatusBar, setShowStatusBar] = createSignal(true)
const [showActivityBar, setShowActivityBar] = createSignal(false)
const [showPanel, setShowPanel] = createSignal(false)
return (
<Example title="With Checkboxes" class="items-center">
<DropdownMenu>
<DropdownMenuTrigger class={buttonVariants({ variant: "outline" }) + " w-fit"}>Checkboxes</DropdownMenuTrigger>
<DropdownMenuContent class="min-w-40">
<DropdownMenuGroup>
<DropdownMenuLabel>Appearance</DropdownMenuLabel>
<DropdownMenuCheckboxItem checked={showStatusBar()} onChange={setShowStatusBar}>
<Layout />
Status Bar
</DropdownMenuCheckboxItem>
<DropdownMenuCheckboxItem checked={showActivityBar()} onChange={setShowActivityBar} disabled>
<Activity />
Activity Bar
</DropdownMenuCheckboxItem>
<DropdownMenuCheckboxItem checked={showPanel()} onChange={setShowPanel}>
<PanelLeft />
Panel
</DropdownMenuCheckboxItem>
</DropdownMenuGroup>
</DropdownMenuContent>
</DropdownMenu>
</Example>
)
}
function DropdownMenuWithCheckboxesIcons() {
const [email, setEmail] = createSignal(true)
const [sms, setSms] = createSignal(false)
const [push, setPush] = createSignal(true)
return (
<Example title="Checkboxes with Icons" class="items-center">
<DropdownMenu>
<DropdownMenuTrigger class={buttonVariants({ variant: "outline" }) + " w-fit"}>
Notifications
</DropdownMenuTrigger>
<DropdownMenuContent class="min-w-56">
<DropdownMenuGroup>
<DropdownMenuLabel>Notification Preferences</DropdownMenuLabel>
<DropdownMenuCheckboxItem checked={email()} onChange={setEmail}>
<Mail />
Email notifications
</DropdownMenuCheckboxItem>
<DropdownMenuCheckboxItem checked={sms()} onChange={setSms}>
<MessageSquare />
SMS notifications
</DropdownMenuCheckboxItem>
<DropdownMenuCheckboxItem checked={push()} onChange={setPush}>
<Bell />
Push notifications
</DropdownMenuCheckboxItem>
</DropdownMenuGroup>
</DropdownMenuContent>
</DropdownMenu>
</Example>
)
}
function DropdownMenuWithRadio() {
const [position, setPosition] = createSignal("bottom")
return (
<Example title="With Radio Group" class="items-center">
<DropdownMenu>
<DropdownMenuTrigger class={buttonVariants({ variant: "outline" }) + " w-fit"}>Radio Group</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuGroup>
<DropdownMenuLabel>Panel Position</DropdownMenuLabel>
<DropdownMenuRadioGroup value={position()} onChange={setPosition}>
<DropdownMenuRadioItem value="top">
<ArrowUp />
Top
</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="bottom">
<ArrowDown />
Bottom
</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="right" disabled>
<ArrowRight />
Right
</DropdownMenuRadioItem>
</DropdownMenuRadioGroup>
</DropdownMenuGroup>
</DropdownMenuContent>
</DropdownMenu>
</Example>
)
}
function DropdownMenuWithRadioIcons() {
const [paymentMethod, setPaymentMethod] = createSignal("card")
return (
<Example title="Radio with Icons" class="items-center">
<DropdownMenu>
<DropdownMenuTrigger class={buttonVariants({ variant: "outline" }) + " w-fit"}>
Payment Method
</DropdownMenuTrigger>
<DropdownMenuContent class="min-w-56">
<DropdownMenuGroup>
<DropdownMenuLabel>Select Payment Method</DropdownMenuLabel>
<DropdownMenuRadioGroup value={paymentMethod()} onChange={setPaymentMethod}>
<DropdownMenuRadioItem value="card">
<CreditCard />
Credit Card
</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="paypal">
<Wallet />
PayPal
</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="bank">
<Building2 />
Bank Transfer
</DropdownMenuRadioItem>
</DropdownMenuRadioGroup>
</DropdownMenuGroup>
</DropdownMenuContent>
</DropdownMenu>
</Example>
)
}
function DropdownMenuWithDestructive() {
return (
<Example title="With Destructive Items" class="items-center">
<DropdownMenu>
<DropdownMenuTrigger class={buttonVariants({ variant: "outline" }) + " w-fit"}>Actions</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem>
<Pencil />
Edit
</DropdownMenuItem>
<DropdownMenuItem>
<Share />
Share
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem>
<Archive />
Archive
</DropdownMenuItem>
<DropdownMenuItem variant="destructive">
<Trash />
Delete
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</Example>
)
}
function AvatarMenuContent() {
return (
<>
<DropdownMenuGroup>
<DropdownMenuItem>
<BadgeCheck />
Account
</DropdownMenuItem>
<DropdownMenuItem>
<CreditCard />
Billing
</DropdownMenuItem>
<DropdownMenuItem>
<Bell />
Notifications
</DropdownMenuItem>
</DropdownMenuGroup>
<DropdownMenuSeparator />
<DropdownMenuItem>
<LogOut />
Sign Out
</DropdownMenuItem>
</>
)
}
function DropdownMenuWithAvatar() {
return (
<Example title="With Avatar">
<div class="flex items-center justify-between gap-4">
<DropdownMenu>
<DropdownMenuTrigger
class={buttonVariants({ variant: "outline" }) + " h-12 justify-start px-2 md:max-w-[200px]"}
>
<Avatar>
<AvatarImage src="https://github.com/shadcn.png" alt="Shadcn" />
<AvatarFallback>CN</AvatarFallback>
</Avatar>
<div class="grid flex-1 text-left text-sm leading-tight">
<span class="truncate font-semibold">shadcn</span>
<span class="text-muted-foreground truncate text-xs">[email protected]</span>
</div>
<ChevronsUpDown class="text-muted-foreground ml-auto size-4" />
</DropdownMenuTrigger>
<DropdownMenuContent class="w-[var(--kb-popper-anchor-width)] min-w-56">
<AvatarMenuContent />
</DropdownMenuContent>
</DropdownMenu>
<DropdownMenu placement="top-end">
<DropdownMenuTrigger class={buttonVariants({ variant: "ghost", size: "icon" }) + " rounded-full"}>
<Avatar>
<AvatarImage src="https://github.com/shadcn.png" alt="shadcn" />
<AvatarFallback>CN</AvatarFallback>
</Avatar>
</DropdownMenuTrigger>
<DropdownMenuContent>
<AvatarMenuContent />
</DropdownMenuContent>
</DropdownMenu>
</div>
</Example>
)
}
function DropdownMenuInDialog() {
return (
<Example title="In Dialog" class="items-center justify-center">
<Dialog>
<DialogTrigger class={buttonVariants({ variant: "outline" })}>Open Dialog</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Dropdown Menu Example</DialogTitle>
<DialogDescription>Click the button below to see the dropdown menu.</DialogDescription>
</DialogHeader>
<DropdownMenu>
<DropdownMenuTrigger class={buttonVariants({ variant: "outline" }) + " w-fit"}>
Open Menu
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem>
<Copy />
Copy
</DropdownMenuItem>
<DropdownMenuItem>
<Scissors />
Cut
</DropdownMenuItem>
<DropdownMenuItem>
<Clipboard />
Paste
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuSub>
<DropdownMenuSubTrigger>More Options</DropdownMenuSubTrigger>
<DropdownMenuPortal>
<DropdownMenuSubContent>
<DropdownMenuItem>Save Page...</DropdownMenuItem>
<DropdownMenuItem>Create Shortcut...</DropdownMenuItem>
<DropdownMenuItem>Name Window...</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem>Developer Tools</DropdownMenuItem>
</DropdownMenuSubContent>
</DropdownMenuPortal>
</DropdownMenuSub>
<DropdownMenuSeparator />
<DropdownMenuItem variant="destructive">
<Trash />
Delete
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</DialogContent>
</Dialog>
</Example>
)
}
function DropdownMenuWithInset() {
const [showBookmarks, setShowBookmarks] = createSignal(true)
const [showUrls, setShowUrls] = createSignal(false)
const [theme, setTheme] = createSignal("system")
return (
<Example title="With Inset" class="items-center">
<DropdownMenu>
<DropdownMenuTrigger class={buttonVariants({ variant: "outline" }) + " w-fit"}>Open</DropdownMenuTrigger>
<DropdownMenuContent class="w-44">
<DropdownMenuGroup>
<DropdownMenuLabel>Actions</DropdownMenuLabel>
<DropdownMenuItem>
<Copy />
Copy
</DropdownMenuItem>
<DropdownMenuItem>
<Scissors />
Cut
</DropdownMenuItem>
<DropdownMenuItem inset>Paste</DropdownMenuItem>
</DropdownMenuGroup>
<DropdownMenuSeparator />
<DropdownMenuGroup>
<DropdownMenuLabel inset>Appearance</DropdownMenuLabel>
<DropdownMenuCheckboxItem inset checked={showBookmarks()} onChange={setShowBookmarks}>
Bookmarks
</DropdownMenuCheckboxItem>
<DropdownMenuCheckboxItem inset checked={showUrls()} onChange={setShowUrls}>
Full URLs
</DropdownMenuCheckboxItem>
</DropdownMenuGroup>
<DropdownMenuSeparator />
<DropdownMenuGroup>
<DropdownMenuLabel inset>Theme</DropdownMenuLabel>
<DropdownMenuRadioGroup value={theme()} onChange={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>
</Example>
)
}
function DropdownMenuComplex() {
const [email, setEmail] = createSignal(true)
const [sms, setSms] = createSignal(false)
const [theme, setTheme] = createSignal("light")
return (
<Example title="Complex" class="items-center">
<DropdownMenu>
<DropdownMenuTrigger class={buttonVariants({ variant: "outline" }) + " w-fit"}>
Complex Menu
</DropdownMenuTrigger>
<DropdownMenuContent class="w-48">
<DropdownMenuGroup>
<DropdownMenuLabel>File</DropdownMenuLabel>
<DropdownMenuItem>
<File />
New File
<DropdownMenuShortcut>⌘N</DropdownMenuShortcut>
</DropdownMenuItem>
<DropdownMenuItem>
<Folder />
New Folder
<DropdownMenuShortcut>⇧⌘N</DropdownMenuShortcut>
</DropdownMenuItem>
<DropdownMenuSub>
<DropdownMenuSubTrigger>
<FolderOpen />
Open Recent
</DropdownMenuSubTrigger>
<DropdownMenuPortal>
<DropdownMenuSubContent>
<DropdownMenuGroup>
<DropdownMenuLabel>Recent Projects</DropdownMenuLabel>
<DropdownMenuItem>
<FileCode />
Project Alpha
</DropdownMenuItem>
<DropdownMenuItem>
<FileCode />
Project Beta
</DropdownMenuItem>
<DropdownMenuSub>
<DropdownMenuSubTrigger>
<MoreHorizontal />
More Projects
</DropdownMenuSubTrigger>
<DropdownMenuPortal>
<DropdownMenuSubContent>
<DropdownMenuItem>
<FileCode />
Project Gamma
</DropdownMenuItem>
<DropdownMenuItem>
<FileCode />
Project Delta
</DropdownMenuItem>
</DropdownMenuSubContent>
</DropdownMenuPortal>
</DropdownMenuSub>
</DropdownMenuGroup>
<DropdownMenuSeparator />
<DropdownMenuGroup>
<DropdownMenuItem>
<FolderSearch />
Browse...
</DropdownMenuItem>
</DropdownMenuGroup>
</DropdownMenuSubContent>
</DropdownMenuPortal>
</DropdownMenuSub>
<DropdownMenuSeparator />
<DropdownMenuItem>
<Save />
Save
<DropdownMenuShortcut>⌘S</DropdownMenuShortcut>
</DropdownMenuItem>
</DropdownMenuGroup>
<DropdownMenuSeparator />
<DropdownMenuGroup>
<DropdownMenuLabel>View</DropdownMenuLabel>
<DropdownMenuCheckboxItem checked={email()} onChange={setEmail}>
<Eye />
Show Sidebar
</DropdownMenuCheckboxItem>
<DropdownMenuCheckboxItem checked={sms()} onChange={setSms}>
<Layout />
Show Status Bar
</DropdownMenuCheckboxItem>
<DropdownMenuSub>
<DropdownMenuSubTrigger>
<Palette />
Theme
</DropdownMenuSubTrigger>
<DropdownMenuPortal>
<DropdownMenuSubContent>
<DropdownMenuGroup>
<DropdownMenuLabel>Appearance</DropdownMenuLabel>
<DropdownMenuRadioGroup value={theme()} onChange={setTheme}>
<DropdownMenuRadioItem value="light">
<Sun />
Light
</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="dark">
<Moon />
Dark
</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="system">
<Monitor />
System
</DropdownMenuRadioItem>
</DropdownMenuRadioGroup>
</DropdownMenuGroup>
</DropdownMenuSubContent>
</DropdownMenuPortal>
</DropdownMenuSub>
</DropdownMenuGroup>
<DropdownMenuSeparator />
<DropdownMenuGroup>
<DropdownMenuLabel>Account</DropdownMenuLabel>
<DropdownMenuItem>
<User />
Profile
<DropdownMenuShortcut>⇧⌘P</DropdownMenuShortcut>
</DropdownMenuItem>
<DropdownMenuItem>
<CreditCard />
Billing
</DropdownMenuItem>
</DropdownMenuGroup>
<DropdownMenuSeparator />
<DropdownMenuGroup>
<DropdownMenuItem variant="destructive">
<LogOut />
Sign Out
<DropdownMenuShortcut>⇧⌘Q</DropdownMenuShortcut>
</DropdownMenuItem>
</DropdownMenuGroup>
</DropdownMenuContent>
</DropdownMenu>
</Example>
)
}Parts
| Component | Description |
|---|---|
DropdownMenu | Root container (manages open state) |
DropdownMenuTrigger | Button that opens the menu |
DropdownMenuContent | The popup panel (includes Portal) |
DropdownMenuItem | A menu item |
DropdownMenuCheckboxItem | A toggleable checkbox menu item |
DropdownMenuRadioGroup | Groups radio items |
DropdownMenuRadioItem | A radio menu item |
DropdownMenuGroup | Groups related items |
DropdownMenuLabel | A non-interactive label for a group |
DropdownMenuSeparator | A visual separator between items |
DropdownMenuShortcut | Displays a keyboard shortcut hint |
DropdownMenuSub | Root for a submenu |
DropdownMenuSubTrigger | Item that opens a submenu (includes chevron icon) |
DropdownMenuSubContent | The submenu popup panel |