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
A select with a default value.
"use client"
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@workspace/ui/components/select"
const sexes = [
{ label: "Female", value: "female" },
{ label: "Male", value: "male" },
{ label: "Intersex", value: "intersex" },
]
export function SelectDemo() {
return (
<Select items={sexes} defaultValue="female">
<SelectTrigger className="w-40">
<SelectValue />
</SelectTrigger>
<SelectContent>
{sexes.map((item) => (
<SelectItem key={item.value} value={item.value}>
{item.label}
</SelectItem>
))}
</SelectContent>
</Select>
)
}
Usage
Use a select to pick one option from a list of five or more. For fewer options, a Radio Group shows them all at once. For actions rather than values, use a Dropdown Menu.
Import it from @workspace/ui/components/select.
Anatomy
- Select — Holds the value. Pass
itemsso the trigger can show the label. - SelectTrigger — The field. Shows a chevron.
- SelectValue — The chosen label inside the trigger.
- SelectContent — The list. By default it opens over the trigger, with the chosen item lined up on it.
- SelectItem — One option. Shows a tick when chosen.
- SelectGroup and SelectLabel — A labelled set of options. A label must sit inside a group.
- SelectSeparator — A line between groups.
Notes
- Without
items, the trigger shows the rawvalue, such asfemaleinstead ofFemale. - For a placeholder, add an item with
value: nulltoitemsand leave it out of the list. - Typing a letter jumps to the matching option.
Examples
Placeholder
Shows "Select a clinic" until the reader picks one.
"use client"
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@workspace/ui/components/select"
const clinics = [
{ label: "Select a clinic", value: null },
{ label: "London Bridge", value: "london-bridge" },
{ label: "Manchester", value: "manchester" },
{ label: "Edinburgh", value: "edinburgh" },
]
export function SelectPlaceholder() {
return (
<Select items={clinics}>
<SelectTrigger className="w-48">
<SelectValue />
</SelectTrigger>
<SelectContent>
{clinics
.filter((item) => item.value !== null)
.map((item) => (
<SelectItem key={item.value} value={item.value}>
{item.label}
</SelectItem>
))}
</SelectContent>
</Select>
)
}
Groups
Options under labels, with separators between groups.
"use client"
import * as React from "react"
import {
Select,
SelectContent,
SelectGroup,
SelectItem,
SelectLabel,
SelectSeparator,
SelectTrigger,
SelectValue,
} from "@workspace/ui/components/select"
const groups = [
{
label: "Lipids",
items: [
{ label: "LDL-C", value: "ldl-c" },
{ label: "HDL-C", value: "hdl-c" },
{ label: "Triglycerides", value: "triglycerides" },
],
},
{
label: "Metabolic",
items: [
{ label: "HbA1c", value: "hba1c" },
{ label: "Fasting glucose", value: "fbs" },
],
},
]
const items = groups.flatMap((group) => group.items)
export function SelectGroups() {
return (
<Select items={items} defaultValue="ldl-c">
<SelectTrigger className="w-48">
<SelectValue />
</SelectTrigger>
<SelectContent>
{groups.map((group, index) => (
<React.Fragment key={group.label}>
{index > 0 && <SelectSeparator />}
<SelectGroup>
<SelectLabel>{group.label}</SelectLabel>
{group.items.map((item) => (
<SelectItem key={item.value} value={item.value}>
{item.label}
</SelectItem>
))}
</SelectGroup>
</React.Fragment>
))}
</SelectContent>
</Select>
)
}
Sizes
sm and default.
"use client"
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@workspace/ui/components/select"
const ranges = [
{ label: "Last 30 days", value: "30d" },
{ label: "Last 6 months", value: "6m" },
{ label: "All time", value: "all" },
]
export function SelectSizes() {
return (
<div className="flex flex-wrap items-center justify-center gap-3">
<Select items={ranges} defaultValue="6m">
<SelectTrigger size="sm" className="w-36">
<SelectValue />
</SelectTrigger>
<SelectContent>
{ranges.map((item) => (
<SelectItem key={item.value} value={item.value}>
{item.label}
</SelectItem>
))}
</SelectContent>
</Select>
<Select items={ranges} defaultValue="6m">
<SelectTrigger className="w-36">
<SelectValue />
</SelectTrigger>
<SelectContent>
{ranges.map((item) => (
<SelectItem key={item.value} value={item.value}>
{item.label}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
)
}
Disabled
A disabled select, and a select with one disabled option.
"use client"
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@workspace/ui/components/select"
const panels = [
{ label: "Core panel", value: "core" },
{ label: "Advanced panel", value: "advanced" },
{ label: "Genetic panel", value: "genetic" },
]
export function SelectDisabled() {
return (
<div className="flex flex-wrap items-center justify-center gap-3">
<Select items={panels} defaultValue="core" disabled>
<SelectTrigger className="w-40">
<SelectValue />
</SelectTrigger>
<SelectContent>
{panels.map((item) => (
<SelectItem key={item.value} value={item.value}>
{item.label}
</SelectItem>
))}
</SelectContent>
</Select>
<Select items={panels} defaultValue="core">
<SelectTrigger className="w-40">
<SelectValue />
</SelectTrigger>
<SelectContent>
{panels.map((item) => (
<SelectItem
key={item.value}
value={item.value}
disabled={item.value === "genetic"}
>
{item.label}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
)
}
Props
These are the props you set most often. Unlisted props pass through to the underlying element.
Select
| Prop | Type | Default | Description |
|---|---|---|---|
items | { label, value }[] | — | Labels for each value, shown in the trigger. |
defaultValue | string | — | Chosen on first render. |
value | string | — | The value when controlled. |
onValueChange | (value) => void | — | Called when the choice changes. |
disabled | boolean | false | Blocks the whole field. |
name | string | — | Field name for form submission. |
SelectTrigger
| Prop | Type | Default | Description |
|---|---|---|---|
size | "default" or "sm" | default | 28 or 24 pixels tall. |
SelectContent
| Prop | Type | Default | Description |
|---|---|---|---|
alignItemWithTrigger | boolean | true | Opens over the trigger with the chosen item lined up. Set to false to open below. |
side | "top", "bottom", "left", or "right" | bottom | Side to open on when not aligned with the trigger. |
align | "start", "center", or "end" | center | Alignment along that side. |
sideOffset | number | 4 | Gap from the trigger, in pixels. |
SelectItem
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | — | Value of the option. |
disabled | boolean | false | Blocks the option. |