Starting your winter arc? 🥶 Get 25% off every plan and template with

Dropdown Menu

Compact actions from any trigger, with grouped sections, nested submenus, checkbox and radio items, and shortcuts.

Loading preview

Examples

Practical examples and common states for the same installable component.

Grouped

Organizes related menu actions into labeled sections with separators.

examples/dropdown-menu-grouped.tsx
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuShortcut,
DropdownMenuTrigger,
} from "@/components/wensity/dropdown-menu";
import { IconClipboard, IconCopy, IconFileText, IconFolder } from "@tabler/icons-react";
export function GroupedDropdown() {
return (
<DropdownMenu>
<DropdownMenuTrigger>Edit</DropdownMenuTrigger>
<DropdownMenuContent className="w-52">
<DropdownMenuLabel>Clipboard</DropdownMenuLabel>
<DropdownMenuGroup>
<DropdownMenuItem>
<IconCopy />
Copy
<DropdownMenuShortcut keys={["⌘", "C"]} />
</DropdownMenuItem>
<DropdownMenuItem>
<IconClipboard />
Paste
<DropdownMenuShortcut keys={["⌘", "V"]} />
</DropdownMenuItem>
</DropdownMenuGroup>
<DropdownMenuSeparator />
<DropdownMenuLabel>File</DropdownMenuLabel>
<DropdownMenuGroup>
<DropdownMenuItem>
<IconFileText />
New file
</DropdownMenuItem>
<DropdownMenuItem>
<IconFolder />
New folder
</DropdownMenuItem>
</DropdownMenuGroup>
</DropdownMenuContent>
</DropdownMenu>
);
}

Nested

Displays additional actions through submenus with chevron indicators.

examples/dropdown-menu-nested.tsx
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuSeparator,
DropdownMenuSub,
DropdownMenuSubContent,
DropdownMenuSubTrigger,
DropdownMenuTrigger,
} from "@/components/wensity/dropdown-menu";
import { IconCloudDownload, IconDownload, IconFileExport, IconLink, IconMail } from "@tabler/icons-react";
export function NestedDropdown() {
return (
<DropdownMenu>
<DropdownMenuTrigger>Share</DropdownMenuTrigger>
<DropdownMenuContent className="w-48">
<DropdownMenuItem>
<IconLink />
Copy link
</DropdownMenuItem>
<DropdownMenuItem>
<IconMail />
Email
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuSub>
<DropdownMenuSubTrigger>
<IconDownload />
Export as
</DropdownMenuSubTrigger>
<DropdownMenuSubContent>
<DropdownMenuItem>
<IconFileExport />
PDF
</DropdownMenuItem>
<DropdownMenuItem>
<IconFileExport />
CSV
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem>
<IconCloudDownload />
Archive (.zip)
</DropdownMenuItem>
</DropdownMenuSubContent>
</DropdownMenuSub>
</DropdownMenuContent>
</DropdownMenu>
);
}

Checkbox

Toggle multiple selectable options with check indicators.

examples/dropdown-menu-checkbox.tsx
"use client";
import * as React from "react";
import {
DropdownMenu,
DropdownMenuCheckboxItem,
DropdownMenuContent,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuShortcut,
DropdownMenuTrigger,
} from "@/components/wensity/dropdown-menu";
import { IconSettings } from "@tabler/icons-react";
export function CheckboxDropdown() {
const [showGrid, setShowGrid] = React.useState(true);
const [showRuler, setShowRuler] = React.useState(false);
return (
<DropdownMenu>
<DropdownMenuTrigger>
<IconSettings />
View
</DropdownMenuTrigger>
<DropdownMenuContent className="w-48">
<DropdownMenuLabel>Canvas</DropdownMenuLabel>
<DropdownMenuCheckboxItem
checked={showGrid}
onCheckedChange={setShowGrid}
>
Show grid
<DropdownMenuShortcut keys={["⌘", "'"]} />
</DropdownMenuCheckboxItem>
<DropdownMenuCheckboxItem
checked={showRuler}
onCheckedChange={setShowRuler}
>
Show ruler
<DropdownMenuShortcut keys={["⌘", "R"]} />
</DropdownMenuCheckboxItem>
<DropdownMenuSeparator />
<DropdownMenuCheckboxItem checked disabled>
Snap to grid
</DropdownMenuCheckboxItem>
</DropdownMenuContent>
</DropdownMenu>
);
}

Radio

Select one option from a group with dot indicators.

examples/dropdown-menu-radio.tsx
"use client";
import * as React from "react";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuLabel,
DropdownMenuRadioGroup,
DropdownMenuRadioItem,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/components/wensity/dropdown-menu";
import { IconSettings, IconWifi, IconWifiOff } from "@tabler/icons-react";
export function RadioDropdown() {
const [density, setDensity] = React.useState("comfortable");
return (
<DropdownMenu>
<DropdownMenuTrigger>
<IconSettings />
Density
</DropdownMenuTrigger>
<DropdownMenuContent className="w-48">
<DropdownMenuLabel>Row height</DropdownMenuLabel>
<DropdownMenuRadioGroup value={density} onValueChange={setDensity}>
<DropdownMenuRadioItem value="compact">Compact</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="comfortable">Comfortable</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="spacious">Spacious</DropdownMenuRadioItem>
</DropdownMenuRadioGroup>
<DropdownMenuSeparator />
<DropdownMenuLabel>Status</DropdownMenuLabel>
<DropdownMenuRadioGroup value="online">
<DropdownMenuRadioItem value="online">
<IconWifi className="text-emerald-500" />
Online
</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="offline" disabled>
<IconWifiOff />
Offline
</DropdownMenuRadioItem>
</DropdownMenuRadioGroup>
</DropdownMenuContent>
</DropdownMenu>
);
}

Destructive

Highlights dangerous or irreversible actions with red styling.

examples/dropdown-menu-destructive.tsx
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuShortcut,
DropdownMenuTrigger,
} from "@/components/wensity/dropdown-menu";
import { IconArrowBigUp, IconCopy, IconPencil, IconTrash } from "@tabler/icons-react";
export function DestructiveDropdown() {
return (
<DropdownMenu>
<DropdownMenuTrigger>More</DropdownMenuTrigger>
<DropdownMenuContent className="w-52">
<DropdownMenuLabel>Project</DropdownMenuLabel>
<DropdownMenuItem>
<IconPencil />
Rename
</DropdownMenuItem>
<DropdownMenuItem>
<IconCopy />
Duplicate
<DropdownMenuShortcut keys={["⌘", "D"]} />
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuLabel>Danger zone</DropdownMenuLabel>
<DropdownMenuItem destructive>
<IconArrowBigUp />
Archive
</DropdownMenuItem>
<DropdownMenuItem destructive>
<IconTrash />
Delete permanently
<DropdownMenuShortcut keys={["⌘", "⌫"]} />
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
}

Installation

Run the following command

~/your-project
pnpm dlx wensity@latest add dropdown-menu

Usage

Import DropdownMenu from @/components/wensity/dropdown-menu and render it anywhere in your React or Next.js app. The source lands in your own repo, so every prop, class and animation below is yours to edit.

app/example.tsx
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuShortcut,
DropdownMenuTrigger,
} from "@/components/wensity/dropdown-menu";
export function DropdownMenuDemo() {
return (
<DropdownMenu>
<DropdownMenuTrigger>Settings</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuLabel>Account</DropdownMenuLabel>
<DropdownMenuGroup>
<DropdownMenuItem>
Profile
<DropdownMenuShortcut keys={["⌘", "P"]} />
</DropdownMenuItem>
<DropdownMenuItem>
Billing
<DropdownMenuShortcut keys={["⌘", "B"]} />
</DropdownMenuItem>
</DropdownMenuGroup>
<DropdownMenuSeparator />
<DropdownMenuItem destructive>
Delete account
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
}

Props

PropTypeDefaultDescription
openboolean-Controlled open state.
defaultOpenboolean-Initial open state when uncontrolled.
onOpenChange(open: boolean) => void-Called when the menu opens or closes.
modalbooleanfalseBlocks interaction with the page behind while the menu is open.

Featured in React navbar components.