Getting Started
Components
- Accordion
- Alert
- Alert Dialog
- Avatar
- Badge
- Button
- Calendar
- Card
- Carousel
- Chart
- Checkbox
- Circular Progress
- Collapsible
- Compare Slider
- Dialog
- Dropdown Menu
- Gauge
- Input
- Label
- Marquee
- Navigation Menu
- Number Field
- Pagination
- Popover
- Progress
- Radio Group
- Scroll Area
- Select
- Separator
- Sheet
- Sidebar
- Skeleton
- Slider
- Switch
- Table
- Tabs
- Textarea
- Toggle
- Tooltip
Demos
An account menu with icons, shortcuts, and a destructive item.
"use client"
import { DownloadIcon, LogOutIcon, SettingsIcon, UserIcon } from "lucide-react"
import { Button } from "@workspace/ui/components/button"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuShortcut,
DropdownMenuTrigger,
} from "@workspace/ui/components/dropdown-menu"
export function DropdownMenuDemo() {
return (
<DropdownMenu>
<DropdownMenuTrigger render={<Button variant="outline" />}>
Account
</DropdownMenuTrigger>
<DropdownMenuContent className="w-48">
<DropdownMenuGroup>
<DropdownMenuLabel>Alex Morgan</DropdownMenuLabel>
<DropdownMenuItem>
<UserIcon />
Profile
<DropdownMenuShortcut>⌘P</DropdownMenuShortcut>
</DropdownMenuItem>
<DropdownMenuItem>
<DownloadIcon />
Export reports
</DropdownMenuItem>
<DropdownMenuItem>
<SettingsIcon />
Settings
<DropdownMenuShortcut>⌘,</DropdownMenuShortcut>
</DropdownMenuItem>
</DropdownMenuGroup>
<DropdownMenuSeparator />
<DropdownMenuItem variant="destructive">
<LogOutIcon />
Sign out
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
)
}
Usage
Use a dropdown menu to group actions that do not need to be on screen all the time, such as account options or the actions on a report. To pick a value for a form field, use a Select.
Import it from @workspace/ui/components/dropdown-menu.
Anatomy
- DropdownMenu — Holds the open state.
- DropdownMenuTrigger — Opens the menu. Pass a button through
render. - DropdownMenuContent — The floating panel.
- DropdownMenuItem — An action. Runs
onClickand closes the menu. - DropdownMenuGroup and DropdownMenuLabel — A labelled set of items. A label must sit inside a group.
- DropdownMenuSeparator — A line between sets of items.
- DropdownMenuShortcut — A keyboard hint at the end of an item. It is only a hint; bind the key yourself.
- DropdownMenuCheckboxItem — An item that toggles on and off.
- DropdownMenuRadioGroup and DropdownMenuRadioItem — Items where one is chosen.
- DropdownMenuSub, DropdownMenuSubTrigger, and DropdownMenuSubContent — A nested menu.
Notes
- Arrow keys move between items, and typing a letter jumps to the matching item.
- Put destructive items last, after a separator.
- Keep menus short. Nest at most one level deep.
Examples
Checkboxes
Items that toggle filters on and off. The menu stays open while you click them.
"use client"
import * as React from "react"
import { Button } from "@workspace/ui/components/button"
import {
DropdownMenu,
DropdownMenuCheckboxItem,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuLabel,
DropdownMenuTrigger,
} from "@workspace/ui/components/dropdown-menu"
export function DropdownMenuCheckboxes() {
const [inRange, setInRange] = React.useState(true)
const [borderline, setBorderline] = React.useState(true)
const [outOfRange, setOutOfRange] = React.useState(true)
return (
<DropdownMenu>
<DropdownMenuTrigger render={<Button variant="outline" />}>
Filter results
</DropdownMenuTrigger>
<DropdownMenuContent className="w-44">
<DropdownMenuGroup>
<DropdownMenuLabel>Show</DropdownMenuLabel>
<DropdownMenuCheckboxItem checked={inRange} onCheckedChange={setInRange}>
In range
</DropdownMenuCheckboxItem>
<DropdownMenuCheckboxItem
checked={borderline}
onCheckedChange={setBorderline}
>
Borderline
</DropdownMenuCheckboxItem>
<DropdownMenuCheckboxItem
checked={outOfRange}
onCheckedChange={setOutOfRange}
>
Out of range
</DropdownMenuCheckboxItem>
</DropdownMenuGroup>
</DropdownMenuContent>
</DropdownMenu>
)
}
Radio group
Choose one option. The trigger shows the current choice.
"use client"
import * as React from "react"
import { Button } from "@workspace/ui/components/button"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuLabel,
DropdownMenuRadioGroup,
DropdownMenuRadioItem,
DropdownMenuTrigger,
} from "@workspace/ui/components/dropdown-menu"
const units = {
conventional: "mg/dL",
si: "mmol/L",
}
export function DropdownMenuRadio() {
const [unit, setUnit] = React.useState<keyof typeof units>("conventional")
return (
<DropdownMenu>
<DropdownMenuTrigger render={<Button variant="outline" />}>
Units: {units[unit]}
</DropdownMenuTrigger>
<DropdownMenuContent className="w-44">
<DropdownMenuGroup>
<DropdownMenuLabel>Units</DropdownMenuLabel>
<DropdownMenuRadioGroup
value={unit}
onValueChange={(value) => setUnit(value as keyof typeof units)}
>
<DropdownMenuRadioItem value="conventional">
Conventional (mg/dL)
</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="si">SI (mmol/L)</DropdownMenuRadioItem>
</DropdownMenuRadioGroup>
</DropdownMenuGroup>
</DropdownMenuContent>
</DropdownMenu>
)
}
Submenu
A nested menu that opens to the side. Add a chevron to the trigger yourself.
"use client"
import { ChevronRightIcon, FileTextIcon, MailIcon, ShareIcon } from "lucide-react"
import { Button } from "@workspace/ui/components/button"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuSub,
DropdownMenuSubContent,
DropdownMenuSubTrigger,
DropdownMenuTrigger,
} from "@workspace/ui/components/dropdown-menu"
export function DropdownMenuSubmenu() {
return (
<DropdownMenu>
<DropdownMenuTrigger render={<Button variant="outline" />}>
Report
</DropdownMenuTrigger>
<DropdownMenuContent className="w-44">
<DropdownMenuItem>
<FileTextIcon />
Open
</DropdownMenuItem>
<DropdownMenuSub>
<DropdownMenuSubTrigger>
<ShareIcon />
Share
<ChevronRightIcon className="ms-auto rtl:rotate-180" />
</DropdownMenuSubTrigger>
<DropdownMenuSubContent>
<DropdownMenuItem>
<MailIcon />
Email
</DropdownMenuItem>
<DropdownMenuItem>Copy link</DropdownMenuItem>
<DropdownMenuItem>Send to GP</DropdownMenuItem>
</DropdownMenuSubContent>
</DropdownMenuSub>
</DropdownMenuContent>
</DropdownMenu>
)
}
Props
These are the props you set most often. Unlisted props pass through to the underlying element.
DropdownMenu
| Prop | Type | Default | Description |
|---|---|---|---|
open | boolean | — | Open state when controlled. |
onOpenChange | (open) => void | — | Called when the menu opens or closes. |
DropdownMenuContent
| Prop | Type | Default | Description |
|---|---|---|---|
side | "top", "bottom", "left", "right", "inline-start", or "inline-end" | bottom | Side of the trigger to open on. |
align | "start", "center", or "end" | start | Alignment along that side. |
sideOffset | number | 4 | Gap from the trigger, in pixels. |
alignOffset | number | 0 | Shift along the side, in pixels. |
DropdownMenuItem
| Prop | Type | Default | Description |
|---|---|---|---|
variant | "default" or "destructive" | default | destructive colours the item red. |
inset | boolean | false | Indents the item to line up with items that have icons. |
disabled | boolean | false | Blocks the item. |
onClick | (event) => void | — | Runs the action. |
DropdownMenuCheckboxItem
| Prop | Type | Default | Description |
|---|---|---|---|
checked | boolean | — | State when controlled. |
onCheckedChange | (checked) => void | — | Called when the item toggles. |
DropdownMenuRadioGroup
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | — | The chosen item when controlled. |
onValueChange | (value) => void | — | Called when the choice changes. |