Dropdown Menu
Displays a menu of actions or options triggered by a button.
Preview
import { useState } from "react";
import {
DropdownMenu,
DropdownMenuTrigger,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuCheckboxItem,
DropdownMenuRadioItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuShortcut,
DropdownMenuGroup,
DropdownMenuSub,
DropdownMenuSubContent,
DropdownMenuSubTrigger,
DropdownMenuRadioGroup,
} from "@/components/ui/DropdownMenu";
import { Button } from "@/components/ui/Button";
export function DropdownMenuDemo() {
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="menu">Open Menu</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-20">
<DropdownMenuLabel>My Account</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuGroup>
<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 />
<DropdownMenuGroup>
<DropdownMenuItem>Team</DropdownMenuItem>
<DropdownMenuSub>
<DropdownMenuSubTrigger>Invite users</DropdownMenuSubTrigger>
<DropdownMenuSubContent>
<DropdownMenuItem>Email</DropdownMenuItem>
<DropdownMenuItem>Message</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem>More...</DropdownMenuItem>
</DropdownMenuSubContent>
</DropdownMenuSub>
<DropdownMenuItem>New Team</DropdownMenuItem>
</DropdownMenuGroup>
<DropdownMenuSeparator />
<DropdownMenuItem>
Log out
<DropdownMenuShortcut>⇧⌘Q</DropdownMenuShortcut>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
)
}Installation
Make sure that namespace is set in your component.json file. Namespace docs: Learn more about namespaces
pnpm dlx shadcn@latest add @aura/dropdown-menuManual
Install the following dependencies:
pnpm install @radix-ui/react-icons radix-uiCopy and paste the class names utility into your utils/class-names.ts file.
import { clsx, type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
Copy and paste the DropdownMenu component into your components/ui/DropdownMenu.tsx file.
"use client";
/**
* @description Displays a menu of actions or options triggered by a button.
*/
import * as React from "react";
import { DropdownMenu as DropdownMenuRadix } from "radix-ui";
import {
CheckIcon,
ChevronRightIcon,
CircleIcon,
DotFilledIcon,
} from "@radix-ui/react-icons";
import { cn } from "@/utils/class-names";
function DropdownMenu({
...props
}: React.ComponentProps<typeof DropdownMenuRadix.Root>) {
return <DropdownMenuRadix.Root data-slot="dropdown-menu" {...props} />;
}
function DropdownMenuPortal({
...props
}: React.ComponentProps<typeof DropdownMenuRadix.Portal>) {
return (
<DropdownMenuRadix.Portal data-slot="dropdown-menu-portal" {...props} />
);
}
function DropdownMenuTrigger({
className,
...props
}: React.ComponentProps<typeof DropdownMenuRadix.Trigger>) {
return (
<DropdownMenuRadix.Trigger
data-slot="dropdown-menu-trigger"
className={cn(className)}
{...props}
/>
);
}
function DropdownMenuContent({
className,
...props
}: React.ComponentProps<typeof DropdownMenuRadix.Content>) {
return (
<DropdownMenuRadix.Portal>
<DropdownMenuRadix.Content
data-slot="dropdown-menu-content"
collisionPadding={8}
className={cn(
className,
"bg-gray-1 border border-gray-a6 rounded-sm relative shadow-md"
)}
{...props}
/>
</DropdownMenuRadix.Portal>
);
}
function DropdownMenuGroup({
...props
}: React.ComponentProps<typeof DropdownMenuRadix.Group>) {
return <DropdownMenuRadix.Group data-slot="dropdown-menu-group" {...props} />;
}
function DropdownMenuItem({
className,
...props
}: React.ComponentProps<typeof DropdownMenuRadix.Item>) {
return (
<DropdownMenuRadix.Item
data-slot="dropdown-menu-item"
className={cn(
className,
"p-0.5 px-2 hover:bg-accent-3 flex relative cursor-pointer justify-between"
)}
{...props}
/>
);
}
function DropdownMenuCheckboxItem({
children,
className,
...props
}: React.ComponentProps<typeof DropdownMenuRadix.CheckboxItem>) {
return (
<DropdownMenuRadix.CheckboxItem
data-slot="dropdown-menu-checkbox-item"
className={cn(
className,
"p-0.5 px-2 hover:bg-accent-3 flex relative cursor-pointer"
)}
{...props}
>
<span className="absolute left-0.5 top-0 bottom-0 items-center flex justify-center">
<DropdownMenuRadix.ItemIndicator>
<CheckIcon className="text-accent-9" />
</DropdownMenuRadix.ItemIndicator>
</span>
{children}
</DropdownMenuRadix.CheckboxItem>
);
}
function DropdownMenuRadioGroup({
className,
...props
}: React.ComponentProps<typeof DropdownMenuRadix.RadioGroup>) {
return (
<DropdownMenuRadix.RadioGroup
data-slot="dropdown-menu-radio-group"
className={cn(className)}
{...props}
/>
);
}
function DropdownMenuRadioItem({
children,
className,
...props
}: React.ComponentProps<typeof DropdownMenuRadix.RadioItem>) {
return (
<DropdownMenuRadix.RadioItem
data-slot="dropdown-menu-radio-item"
className={cn(
className,
"p-0.5 px-2 hover:bg-accent-3 flex relative cursor-pointer"
)}
{...props}
>
<span className="absolute left-0.5 top-0 bottom-0 items-center flex justify-center">
<DropdownMenuRadix.ItemIndicator>
<DotFilledIcon className="fill-current text-accent-9" />
</DropdownMenuRadix.ItemIndicator>
</span>
{children}
</DropdownMenuRadix.RadioItem>
);
}
function DropdownMenuLabel({
className,
...props
}: React.ComponentProps<typeof DropdownMenuRadix.Label>) {
return (
<DropdownMenuRadix.Label
data-slot="dropdown-menu-label"
className={cn(className, "p-0.5 px-2 text-gray-12")}
{...props}
/>
);
}
function DropdownMenuSeparator({
className,
...props
}: React.ComponentProps<typeof DropdownMenuRadix.Separator>) {
return (
<DropdownMenuRadix.Separator
data-slot="dropdown-menu-separator"
className={cn(className, "m-0.6 h-px bg-gray-a6")}
{...props}
/>
);
}
function DropdownMenuShortcut({ ...props }: React.ComponentProps<"span">) {
return <span data-slot="dropdown-menu-shortcut" {...props} />;
}
function DropdownMenuSub({
...props
}: React.ComponentProps<typeof DropdownMenuRadix.Sub>) {
return <DropdownMenuRadix.Sub data-slot="dropdown-menu-sub" {...props} />;
}
function DropdownMenuSubTrigger({
children,
className,
...props
}: React.ComponentProps<typeof DropdownMenuRadix.SubTrigger>) {
return (
<DropdownMenuRadix.SubTrigger
data-slot="dropdown-menu-sub-trigger"
className={cn(
className,
"p-0.5 px-2 hover:bg-accent-3 flex relative cursor-pointer"
)}
{...props}
>
{children}
<div className="absolute right-0.5 top-0 bottom-0 items-center flex justify-center">
<ChevronRightIcon />
</div>
</DropdownMenuRadix.SubTrigger>
);
}
function DropdownMenuSubContent({
className,
...props
}: React.ComponentProps<typeof DropdownMenuRadix.SubContent>) {
return (
<DropdownMenuRadix.SubContent
data-slot="dropdown-menu-sub-content"
className={cn(
className,
"bg-gray-1 border border-gray-a6 rounded-sm relative shadow-md"
)}
{...props}
/>
);
}
export {
DropdownMenu,
DropdownMenuPortal,
DropdownMenuTrigger,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuLabel,
DropdownMenuItem,
DropdownMenuCheckboxItem,
DropdownMenuRadioGroup,
DropdownMenuRadioItem,
DropdownMenuSeparator,
DropdownMenuShortcut,
DropdownMenuSub,
DropdownMenuSubTrigger,
DropdownMenuSubContent,
};Usage
WithCheckboxes
export const WithCheckboxes = () => {
const [showStatusBar, setShowStatusBar] = useState(true);
const [showActivityBar, setShowActivityBar] = useState(false);
const [showPanel, setShowPanel] = useState(false);
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="menu">Open Menu</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-20">
<DropdownMenuLabel>Appearance</DropdownMenuLabel>
<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>
);
};WithRadioGroup
export const WithRadioGroup = () => {
const [position, setPosition] = useState("bottom");
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="menu">Open Menu</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-20">
<DropdownMenuLabel>Panel Position</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuRadioGroup value={position} onValueChange={setPosition}>
<DropdownMenuRadioItem value="top">Top</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="bottom">Bottom</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="right">Right</DropdownMenuRadioItem>
</DropdownMenuRadioGroup>
</DropdownMenuContent>
</DropdownMenu>
);
};Complex
export const Complex = () => {
const [showStatusBar, setShowStatusBar] = useState(true);
const [showPanel, setShowPanel] = useState(false);
const [position, setPosition] = useState("bottom");
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="menu">Open Menu</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-20">
<DropdownMenuLabel>My Account</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuGroup>
<DropdownMenuItem>
Profile
<DropdownMenuShortcut>⇧⌘P</DropdownMenuShortcut>
</DropdownMenuItem>
<DropdownMenuItem>
Billing
<DropdownMenuShortcut>⌘B</DropdownMenuShortcut>
</DropdownMenuItem>
<DropdownMenuItem>
Settings
<DropdownMenuShortcut>⌘S</DropdownMenuShortcut>
</DropdownMenuItem>
</DropdownMenuGroup>
<DropdownMenuSeparator />
<DropdownMenuLabel>Appearance</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuCheckboxItem
checked={showStatusBar}
onCheckedChange={setShowStatusBar}
>
Status Bar
</DropdownMenuCheckboxItem>
<DropdownMenuCheckboxItem
checked={showPanel}
onCheckedChange={setShowPanel}
>
Panel
</DropdownMenuCheckboxItem>
<DropdownMenuSeparator />
<DropdownMenuLabel>Panel Position</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuRadioGroup value={position} onValueChange={setPosition}>
<DropdownMenuRadioItem value="top">Top</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="bottom">Bottom</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="right">Right</DropdownMenuRadioItem>
</DropdownMenuRadioGroup>
<DropdownMenuSeparator />
<DropdownMenuItem>
Log out
<DropdownMenuShortcut>⇧⌘Q</DropdownMenuShortcut>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
};