Skip to main content

Select

Pick from lists. Custom styling. Simplify complex choices.

Your database is created in the same region.
1'use client';
2
3import { Label } from '@/components/ui/label';
4import { Select } from '@/components/ui/select';
5
6const regions = [
7 { value: 'us-east-1', label: 'US East, Virginia' },
8 { value: 'us-west-2', label: 'US West, Oregon' },
9 { value: 'eu-central-1', label: 'Europe, Frankfurt' },
10 { value: 'sa-east-1', label: 'South America, Sao Paulo' },
11 { value: 'ap-southeast-1', label: 'Asia Pacific, Singapore' },
12];
13
14export function Default() {
15 return (
16 <div className="flex w-full max-w-sm flex-col gap-1.5">
17 <Label htmlFor="deploy-region" description="Your database is created in the same region.">
18 Deployment region
19 </Label>
20 <Select defaultValue="eu-central-1">
21 <Select.Trigger id="deploy-region" placeholder="Pick a region" />
22 <Select.Content>
23 {regions.map((region) => (
24 <Select.Item key={region.value} value={region.value}>
25 {region.label}
26 </Select.Item>
27 ))}
28 </Select.Content>
29 </Select>
30 </div>
31 );
32}

Installation

pnpm dlx nachui add select

Anatomy

1import { Select } from '@/components/ui/select';
1<Select defaultValue="one">
2 <Select.Trigger placeholder="Pick an option" />
3 <Select.Content>
4 <Select.Item value="one">Option 1</Select.Item>
5 <Select.Item value="two">Option 2</Select.Item>
6 </Select.Content>
7</Select>

Composition

Use the following composition to build a Select:
Select
├── Select.Trigger
└── Select.Content
├── Select.Group
│ ├── Select.Label
│ └── Select.Item
└── Select.Separator
The trigger shows the label of the selected item on its own. Pass children to the trigger only when you want to render something else in its place.

Variants

Default

Your database is created in the same region.
1'use client';
2
3import { Label } from '@/components/ui/label';
4import { Select } from '@/components/ui/select';
5
6const regions = [
7 { value: 'us-east-1', label: 'US East, Virginia' },
8 { value: 'us-west-2', label: 'US West, Oregon' },
9 { value: 'eu-central-1', label: 'Europe, Frankfurt' },
10 { value: 'sa-east-1', label: 'South America, Sao Paulo' },
11 { value: 'ap-southeast-1', label: 'Asia Pacific, Singapore' },
12];
13
14export function Default() {
15 return (
16 <div className="flex w-full max-w-sm flex-col gap-1.5">
17 <Label htmlFor="deploy-region" description="Your database is created in the same region.">
18 Deployment region
19 </Label>
20 <Select defaultValue="eu-central-1">
21 <Select.Trigger id="deploy-region" placeholder="Pick a region" />
22 <Select.Content>
23 {regions.map((region) => (
24 <Select.Item key={region.value} value={region.value}>
25 {region.label}
26 </Select.Item>
27 ))}
28 </Select.Content>
29 </Select>
30 </div>
31 );
32}

Grouped Items

Wrap related items in Select.Group and give each group a Select.Label.
1'use client';
2
3import { Label } from '@/components/ui/label';
4import { Select } from '@/components/ui/select';
5
6const teams = [
7 {
8 label: 'Engineering',
9 members: [
10 { value: 'lucia', label: 'Lucia Mendez' },
11 { value: 'marco', label: 'Marco Rivas' },
12 { value: 'priya', label: 'Priya Nair' },
13 ],
14 },
15 {
16 label: 'Design',
17 members: [
18 { value: 'ines', label: 'Ines Duarte' },
19 { value: 'tomas', label: 'Tomas Fuentes' },
20 ],
21 },
22 {
23 label: 'Support',
24 members: [
25 { value: 'noa', label: 'Noa Bergman' },
26 { value: 'hugo', label: 'Hugo Salas' },
27 ],
28 },
29];
30
31export function GroupedItems() {
32 return (
33 <div className="flex w-full max-w-sm flex-col gap-1.5">
34 <Label htmlFor="assignee">Assign ticket to</Label>
35 <Select>
36 <Select.Trigger id="assignee" placeholder="Unassigned" />
37 <Select.Content>
38 {teams.map((team) => (
39 <Select.Group key={team.label}>
40 <Select.Label>{team.label}</Select.Label>
41 {team.members.map((member) => (
42 <Select.Item key={member.value} value={member.value}>
43 {member.label}
44 </Select.Item>
45 ))}
46 </Select.Group>
47 ))}
48 </Select.Content>
49 </Select>
50 </div>
51 );
52}

Keyboard

KeyAction
Enter, Space, ArrowsOpen the list and focus the selected item
ArrowUp, ArrowDownMove between items
Home, EndJump to the first or last item
A letterFocus the next item whose label starts with it
Enter, SpaceSelect the focused item
EscapeClose the list and return focus to the trigger

API Reference

Select

PropTypeDefaultDescription
valuestring-Controlled value
defaultValuestring''Initial value when uncontrolled
onValueChange(value: string) => void-Called when the selected value changes
openboolean-Controlled open state
defaultOpenbooleanfalseInitial open state when uncontrolled
onOpenChange(open: boolean) => void-Called when the open state changes
disabledbooleanfalseDisables the trigger
namestring-Renders a hidden input so the value submits with forms
requiredboolean-Marks the hidden input as required
classNamestring-Additional CSS classes for the wrapper

Select.Trigger

Accepts every button attribute, so id and aria-label work as usual.
PropTypeDefaultDescription
placeholderstring-Text shown when no item is selected
size'sm' | 'default' | 'lg''default'Height and padding of the trigger
childrenReactNode-Replaces the selected label with custom content
classNamestring-Additional CSS classes

Select.Content

PropTypeDefaultDescription
sideOffsetnumber4Gap between the trigger and the list
classNamestring-Additional CSS classes

Select.Item

PropTypeDefaultDescription
valuestring-Value reported when the item is selected
textValuestring-Label shown in the trigger when children are not plain text
disabledbooleanfalseSkips the item in keyboard navigation and blocks selection
classNamestring-Additional CSS classes

Select.Group, Select.Label, Select.Separator

PropTypeDefaultDescription
classNamestring-Additional CSS classes
Found something to improve?

Notice a bug, typo, or missing detail on this page? Help us make the documentation better by opening a GitHub issue.

Create an Issue
Ctrl+I