- Accordion
- Alert
- Alert Dialog
- Autocomplete
- Avatar
- Badge
- Breadcrumb
- Button
- Calendar
- Card
- Checkbox
- Checkbox Group
- Collapsible
- Combobox
- Command
- Date Picker
- Dialog
- DrawerNew
- Empty
- Field
- Fieldset
- Form
- Frame
- Group
- Input
- Input Group
- Kbd
- Label
- Menu
- Meter
- Number Field
- OTP FieldNew
- Pagination
- Popover
- Preview Card
- Progress
- Radio Group
- Scroll Area
- Select
- Separator
- Sheet
- Skeleton
- Slider
- Spinner
- Switch
- Table
- Tabs
- Textarea
- Toast
- Toggle
- Toggle Group
- Toolbar
- Tooltip
Select
A common form component for choosing a predefined value in a dropdown menu.
import {
Select,
SelectItem,
SelectPopup,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
const items = [
{ label: "Next.js", value: "next" },
{ label: "Vite", value: "vite" },
{ label: "Astro", value: "astro" },
];
export default function Particle() {
return (
<Select aria-label="Select framework" defaultValue="next" items={items}>
<SelectTrigger>
<SelectValue />
</SelectTrigger>
<SelectPopup>
{items.map(({ label, value }) => (
<SelectItem key={value} value={value}>
{label}
</SelectItem>
))}
</SelectPopup>
</Select>
);
}
Installation
pnpm dlx shadcn@latest add @coss/select
Usage
import {
Select,
SelectItem,
SelectPopup,
SelectLabel,
SelectTrigger,
SelectValue,
} from "@/components/ui/select"const items = [
{ label: "Select framework", value: null },
{ label: "Next.js", value: "next" },
{ label: "Vite", value: "vite" },
{ label: "Astro", value: "astro" },
]
<Select items={items}>
<SelectTrigger>
<SelectValue />
</SelectTrigger>
<SelectPopup>
<SelectLabel>Frameworks</SelectLabel>
{items.map((item) => (
<SelectItem key={item.value} value={item}>
{item.label}
</SelectItem>
))}
</SelectPopup>
</Select>API Reference
Select
Root component. Alias for Select.Root from Base UI.
SelectTrigger
Trigger button that opens the select dropdown. Styled wrapper for Select.Trigger from Base UI.
| Prop | Type | Default | Description |
|---|---|---|---|
size | "sm" | "default" | "lg" | "default" | Controls the size of the trigger |
SelectValue
Displays the selected value. Styled wrapper for Select.Value from Base UI.
SelectPopup
Popup container for select options. Also exported as SelectContent.
| Prop | Type | Default | Description |
|---|---|---|---|
alignItemWithTrigger | boolean | true | Aligns the selected item with the trigger |
sideOffset | number | 4 | Distance from the trigger in pixels |
SelectItem
Individual select option. Styled wrapper for Select.Item from Base UI with built-in indicator.
SelectGroup
Groups related select items. Alias for Select.Group from Base UI.
SelectLabel
Label for all options in the popup. Styled wrapper for Select.Label from Base UI. Clicking it focuses the select trigger without opening the popup.
SelectGroupLabel
Label for a select group. Styled wrapper for Select.GroupLabel from Base UI.
SelectSeparator
Visual separator between items. Styled wrapper for Select.Separator from Base UI.
SelectButton
A standalone button styled like a SelectTrigger. Use it as a render prop on other trigger components (e.g., ComboboxTrigger, MenuTrigger) to give them select-like appearance.
| Prop | Type | Default | Description |
|---|---|---|---|
size | "sm" | "default" | "lg" | "default" | Controls the size of the button |
import { SelectButton } from "@/components/ui/select"<ComboboxTrigger render={<SelectButton />}>
<ComboboxValue placeholder="Select a fruit" />
</ComboboxTrigger>Examples
For accessible labelling and validation, prefer using the Field component to wrap selects. See the related example: Select field.
Small Size
import {
Select,
SelectItem,
SelectPopup,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
const items = [
{ label: "Next.js", value: "next" },
{ label: "Vite", value: "vite" },
{ label: "Astro", value: "astro" },
];
export default function Particle() {
return (
<Select aria-label="Select framework" items={items}>
<SelectTrigger size="sm">
<SelectValue placeholder="Select framework" />
</SelectTrigger>
<SelectPopup>
{items.map(({ label, value }) => (
<SelectItem key={value} value={value}>
{label}
</SelectItem>
))}
</SelectPopup>
</Select>
);
}
Large Size
import {
Select,
SelectItem,
SelectPopup,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
const items = [
{ label: "Next.js", value: "next" },
{ label: "Vite", value: "vite" },
{ label: "Astro", value: "astro" },
];
export default function Particle() {
return (
<Select aria-label="Select framework" items={items}>
<SelectTrigger size="lg">
<SelectValue placeholder="Select framework" />
</SelectTrigger>
<SelectPopup>
{items.map(({ label, value }) => (
<SelectItem key={value} value={value}>
{label}
</SelectItem>
))}
</SelectPopup>
</Select>
);
}
Disabled
import {
Select,
SelectItem,
SelectPopup,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
const items = [
{ label: "Next.js", value: "next" },
{ label: "Vite", value: "vite" },
{ label: "Astro", value: "astro" },
];
export default function Particle() {
return (
<Select aria-label="Select framework" items={items}>
<SelectTrigger disabled>
<SelectValue placeholder="Select framework" />
</SelectTrigger>
<SelectPopup>
{items.map(({ label, value }) => (
<SelectItem key={value} value={value}>
{label}
</SelectItem>
))}
</SelectPopup>
</Select>
);
}
Without Item Alignment
import {
Select,
SelectItem,
SelectPopup,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
const items = [
{ label: "Next.js", value: "next" },
{ label: "Vite", value: "vite" },
{ label: "Astro", value: "astro" },
];
export default function Particle() {
return (
<Select aria-label="Select framework" items={items}>
<SelectTrigger>
<SelectValue placeholder="Select framework" />
</SelectTrigger>
<SelectPopup alignItemWithTrigger={false}>
{items.map(({ label, value }) => (
<SelectItem key={value} value={value}>
{label}
</SelectItem>
))}
</SelectPopup>
</Select>
);
}
With Groups
import {
Select,
SelectGroup,
SelectGroupLabel,
SelectItem,
SelectPopup,
SelectSeparator,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
const frontend = [
{ label: "Next.js", value: "next" },
{ label: "Vite", value: "vite" },
{ label: "Astro", value: "astro" },
];
const backend = [
{ label: "Express", value: "express" },
{ label: "NestJS", value: "nestjs" },
{ label: "Fastify", value: "fastify" },
{ label: "Django", value: "django" },
{ label: "Flask", value: "flask" },
{ label: "Rails", value: "rails" },
];
export default function Particle() {
return (
<Select aria-label="Select framework" items={[...frontend, ...backend]}>
<SelectTrigger>
<SelectValue placeholder="Select framework" />
</SelectTrigger>
<SelectPopup>
<SelectGroup>
<SelectGroupLabel>Frontend</SelectGroupLabel>
{frontend.map(({ label, value }) => (
<SelectItem key={value} value={value}>
{label}
</SelectItem>
))}
</SelectGroup>
<SelectSeparator />
<SelectGroup>
<SelectGroupLabel>Backend</SelectGroupLabel>
{backend.map(({ label, value }) => (
<SelectItem key={value} value={value}>
{label}
</SelectItem>
))}
</SelectGroup>
</SelectPopup>
</Select>
);
}
With Label
import {
Select,
SelectItem,
SelectLabel,
SelectPopup,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
const items = [
{ label: "Apple", value: "apple" },
{ label: "Banana", value: "banana" },
{ label: "Orange", value: "orange" },
];
export default function Particle() {
return (
<Select aria-label="Select fruit" defaultValue={items[0]} items={items}>
<SelectLabel>Fruits</SelectLabel>
<SelectTrigger>
<SelectValue />
</SelectTrigger>
<SelectPopup>
{items.map((item) => (
<SelectItem key={item.value} value={item}>
{item.label}
</SelectItem>
))}
</SelectPopup>
</Select>
);
}
Multiple Selection
"use client";
import {
Select,
SelectItem,
SelectPopup,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
const languages = {
cpp: "C++",
csharp: "C#",
go: "Go",
java: "Java",
javascript: "JavaScript",
php: "PHP",
python: "Python",
rust: "Rust",
swift: "Swift",
typescript: "TypeScript",
};
type Language = keyof typeof languages;
const values = Object.keys(languages) as Language[];
function renderValue(value: Language[]) {
if (value.length === 0) {
return "Select languages…";
}
const firstLanguage = value[0] ? languages[value[0]] : "";
const additionalLanguages =
value.length > 1 ? ` (+${value.length - 1} more)` : "";
return firstLanguage + additionalLanguages;
}
export default function Particle() {
return (
<Select
aria-label="Select languages"
defaultValue={["javascript", "typescript"]}
multiple
>
<SelectTrigger>
<SelectValue>{renderValue}</SelectValue>
</SelectTrigger>
<SelectPopup alignItemWithTrigger={false}>
{values.map((value) => (
<SelectItem key={value} value={value}>
{languages[value]}
</SelectItem>
))}
</SelectPopup>
</Select>
);
}
With Icon
import { CableIcon } from "lucide-react";
import {
Select,
SelectItem,
SelectPopup,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
const items = [
{ label: "Next.js", value: "next" },
{ label: "Vite", value: "vite" },
{ label: "Astro", value: "astro" },
];
export default function Particle() {
return (
<Select
aria-label="Select framework with icon"
defaultValue="next"
items={items}
>
<SelectTrigger>
<CableIcon aria-hidden="true" />
<SelectValue />
</SelectTrigger>
<SelectPopup alignItemWithTrigger={false}>
{items.map(({ label, value }) => (
<SelectItem key={value} value={value}>
{label}
</SelectItem>
))}
</SelectPopup>
</Select>
);
}
Options with Icon
"use client";
import { Code2Icon, GlobeIcon, LayersIcon, ZapIcon } from "lucide-react";
import {
Select,
SelectItem,
SelectPopup,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
const items = [
{ icon: LayersIcon, label: "Components", value: "components" },
{ icon: ZapIcon, label: "Performance", value: "performance" },
{ icon: GlobeIcon, label: "Network", value: "network" },
{ icon: Code2Icon, label: "Development", value: "development" },
];
export default function Particle() {
return (
<Select
aria-label="Select category"
defaultValue={items[0]}
itemToStringValue={(item) => item.value}
>
<SelectTrigger>
<SelectValue>
{(item) => (
<span className="flex items-center gap-2">
<item.icon />
<span className="truncate">{item.label}</span>
</span>
)}
</SelectValue>
</SelectTrigger>
<SelectPopup>
{items.map((item) => (
<SelectItem key={item.value} value={item}>
<span className="flex items-center gap-2">
<item.icon />
<span className="truncate">{item.label}</span>
</span>
</SelectItem>
))}
</SelectPopup>
</Select>
);
}
With Object Values
"use client";
import {
Select,
SelectItem,
SelectPopup,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
const items = [
{ description: "npx create-next-app", label: "Next.js", value: "next" },
{ description: "npm create vite@latest", label: "Vite", value: "vite" },
{ description: "npm create astro@latest", label: "Astro", value: "astro" },
{ description: "npx create-remix", label: "Remix", value: "remix" },
];
export default function Particle() {
return (
<Select
aria-label="Select framework with command"
defaultValue={items[0]}
itemToStringValue={(item) => item.value}
>
<SelectTrigger className="py-1">
<SelectValue>
{(item) => (
<span className="flex flex-col">
<span className="truncate">{item.label}</span>
<span className="truncate text-muted-foreground text-xs">
{item.description}
</span>
</span>
)}
</SelectValue>
</SelectTrigger>
<SelectPopup>
{items.map((item) => (
<SelectItem key={item.value} value={item}>
<span className="flex flex-col">
<span className="truncate">{item.label}</span>
<span className="truncate text-muted-foreground text-xs">
{item.description}
</span>
</span>
</SelectItem>
))}
</SelectPopup>
</Select>
);
}
SelectButton with Combobox
Use SelectButton as a render prop on ComboboxTrigger to create a combobox that looks like a select.
"use client";
import { SearchIcon } from "lucide-react";
import {
Combobox,
ComboboxEmpty,
ComboboxInput,
ComboboxItem,
ComboboxList,
ComboboxPopup,
ComboboxTrigger,
ComboboxValue,
} from "@/components/ui/combobox";
import { SelectButton } from "@/components/ui/select";
const items = [
{ label: "Apple", value: "apple" },
{ label: "Banana", value: "banana" },
{ label: "Orange", value: "orange" },
{ label: "Grape", value: "grape" },
{ label: "Strawberry", value: "strawberry" },
{ label: "Mango", value: "mango" },
{ label: "Pineapple", value: "pineapple" },
{ label: "Kiwi", value: "kiwi" },
{ label: "Peach", value: "peach" },
{ label: "Pear", value: "pear" },
];
export default function Particle() {
return (
<Combobox items={items}>
<ComboboxTrigger render={<SelectButton />}>
<ComboboxValue placeholder="Select a fruit" />
</ComboboxTrigger>
<ComboboxPopup aria-label="Select a fruit">
<div className="border-b p-2">
<ComboboxInput
className="rounded-md before:rounded-[calc(var(--radius-md)-1px)]"
placeholder="Search fruits..."
showTrigger={false}
startAddon={<SearchIcon />}
/>
</div>
<ComboboxEmpty>No items found.</ComboboxEmpty>
<ComboboxList>
{(item) => (
<ComboboxItem key={item.value} value={item}>
{item.label}
</ComboboxItem>
)}
</ComboboxList>
</ComboboxPopup>
</Combobox>
);
}
Form Integration
"use client";
import type { FormEvent } from "react";
import { useState } from "react";
import { Button } from "@/components/ui/button";
import {
Field,
FieldDescription,
FieldError,
FieldLabel,
} from "@/components/ui/field";
import { Form } from "@/components/ui/form";
import {
Select,
SelectItem,
SelectPopup,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
const items = [
{ label: "Next.js", value: "next" },
{ label: "Vite", value: "vite" },
{ label: "Astro", value: "astro" },
];
export default function Particle() {
const [loading, setLoading] = useState(false);
const onSubmit = async (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
const formData = new FormData(e.currentTarget);
setLoading(true);
await new Promise((r) => setTimeout(r, 800));
setLoading(false);
alert(`Framework: ${formData.get("framework") || ""}`);
};
return (
<Form className="max-w-64" onSubmit={onSubmit}>
<Field>
<FieldLabel>Framework</FieldLabel>
<Select
aria-label="Select framework"
items={items}
name="framework"
required
>
<SelectTrigger>
<SelectValue placeholder="Select a framework" />
</SelectTrigger>
<SelectPopup>
{items.map(({ label, value }) => (
<SelectItem key={value} value={value}>
{label}
</SelectItem>
))}
</SelectPopup>
</Select>
<FieldDescription>Pick your favorite.</FieldDescription>
<FieldError>Please select a value.</FieldError>
</Field>
<Button loading={loading} type="submit">
Submit
</Button>
</Form>
);
}
On This Page