Select
A listbox for choosing a single value from a set of options, triggered by a button. Built on Base UI's select primitive. Looking for a searchable list instead? See Combobox.
Last updated August 7, 2026
Copied from shadcn/ui.
- Improved RTL support — the portaled popup now follows the trigger's local direction instead of only the document's
Overview
import {
Select,
SelectContent,
SelectGroup,
SelectItem,
SelectGroupLabel,
SelectTrigger,
SelectValue,
} from "@/components/ui/select"
const fruits = ["Apple", "Banana", "Blueberry", "Grapes", "Pineapple"]
export function SelectDemoExample() {
return (
<Select>
<SelectTrigger className="w-48">
<SelectValue placeholder="Select a fruit" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectGroupLabel>Fruits</SelectGroupLabel>
{fruits.map((fruit) => (
<SelectItem key={fruit} value={fruit}>
{fruit}
</SelectItem>
))}
</SelectGroup>
</SelectContent>
</Select>
)
}Installation
$ npx shadcn@latest add https://ui.persian-labs.ir/r/select.jsonUsage
import {
Select,
SelectContent,
SelectGroup,
SelectItem,
SelectGroupLabel,
SelectTrigger,
SelectValue,
} from "@/components/ui/select"
const fruits = ["Apple", "Banana", "Blueberry"]
export function Example() {
return (
<Select>
<SelectTrigger className="w-48">
<SelectValue placeholder="Select a fruit" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectGroupLabel>Fruits</SelectGroupLabel>
{fruits.map((fruit) => (
<SelectItem key={fruit} value={fruit}>
{fruit}
</SelectItem>
))}
</SelectGroup>
</SelectContent>
</Select>
)
}Examples
Groups
Use SelectGroup, SelectGroupLabel, and SelectSeparator to organize items.
import {
Select,
SelectContent,
SelectGroup,
SelectItem,
SelectGroupLabel,
SelectSeparator,
SelectTrigger,
SelectValue,
} from "@/components/ui/select"
const fruits = ["Apple", "Banana", "Blueberry"]
const vegetables = ["Carrot", "Broccoli", "Spinach"]
export function SelectGroupsExample() {
return (
<Select>
<SelectTrigger className="w-48">
<SelectValue placeholder="Select an ingredient" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectGroupLabel>Fruits</SelectGroupLabel>
{fruits.map((fruit) => (
<SelectItem key={fruit} value={fruit}>
{fruit}
</SelectItem>
))}
</SelectGroup>
<SelectSeparator />
<SelectGroup>
<SelectGroupLabel>Vegetables</SelectGroupLabel>
{vegetables.map((vegetable) => (
<SelectItem key={vegetable} value={vegetable}>
{vegetable}
</SelectItem>
))}
</SelectGroup>
</SelectContent>
</Select>
)
}Scrollable
A select with many items that scrolls.
import {
Select,
SelectContent,
SelectGroup,
SelectItem,
SelectGroupLabel,
SelectTrigger,
SelectValue,
} from "@/components/ui/select"
const northAmerica = [
"Eastern Standard Time",
"Central Standard Time",
"Mountain Standard Time",
"Pacific Standard Time",
]
const europeAfrica = [
"Greenwich Mean Time",
"Central European Time",
"Eastern European Time",
]
const asia = [
"Moscow Time",
"India Standard Time",
"China Standard Time",
"Japan Standard Time",
]
const australiaPacific = [
"Australian Western Standard Time",
"Australian Eastern Standard Time",
]
export function SelectScrollableExample() {
return (
<Select>
<SelectTrigger className="w-64">
<SelectValue placeholder="Select a timezone" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectGroupLabel>North America</SelectGroupLabel>
{northAmerica.map((zone) => (
<SelectItem key={zone} value={zone}>
{zone}
</SelectItem>
))}
</SelectGroup>
<SelectGroup>
<SelectGroupLabel>Europe & Africa</SelectGroupLabel>
{europeAfrica.map((zone) => (
<SelectItem key={zone} value={zone}>
{zone}
</SelectItem>
))}
</SelectGroup>
<SelectGroup>
<SelectGroupLabel>Asia</SelectGroupLabel>
{asia.map((zone) => (
<SelectItem key={zone} value={zone}>
{zone}
</SelectItem>
))}
</SelectGroup>
<SelectGroup>
<SelectGroupLabel>Australia & Pacific</SelectGroupLabel>
{australiaPacific.map((zone) => (
<SelectItem key={zone} value={zone}>
{zone}
</SelectItem>
))}
</SelectGroup>
</SelectContent>
</Select>
)
}Disabled
Use the disabled prop on Select to disable the whole control, or on an individual SelectItem to disable just that option.
import {
Select,
SelectContent,
SelectGroup,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select"
export function SelectDisabledExample() {
return (
<Select disabled defaultValue="Apple">
<SelectTrigger className="w-48">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectItem value="Apple">Apple</SelectItem>
<SelectItem value="Banana">Banana</SelectItem>
<SelectItem value="Grapes" disabled>
Grapes
</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
)
}Invalid
Add data-invalid to Field and aria-invalid to SelectTrigger to show an error state.
import { Field, FieldError, FieldLabel } from "@/components/ui/field"
import {
Select,
SelectContent,
SelectGroup,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select"
const fruits = ["Apple", "Banana", "Blueberry"]
export function SelectInvalidExample() {
return (
<Field data-invalid className="w-48">
<FieldLabel>Fruit</FieldLabel>
<Select>
<SelectTrigger aria-invalid>
<SelectValue placeholder="Select a fruit" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
{fruits.map((fruit) => (
<SelectItem key={fruit} value={fruit}>
{fruit}
</SelectItem>
))}
</SelectGroup>
</SelectContent>
</Select>
<FieldError>Please select a fruit.</FieldError>
</Field>
)
}Align item with trigger
Use alignItemWithTrigger on SelectContent to control whether the selected item aligns with the trigger (default) or the popup aligns to the trigger's edge instead.
"use client"
import * as React from "react"
import { Button } from "@/components/ui/button"
import {
Select,
SelectContent,
SelectGroup,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select"
const fruits = ["Apple", "Banana", "Blueberry", "Grapes", "Pineapple"]
export function SelectAlignItemExample() {
const [alignItemWithTrigger, setAlignItemWithTrigger] = React.useState(true)
return (
<div className="flex flex-col items-center gap-4">
<Button
type="button"
variant="outline"
size="sm"
onClick={() => setAlignItemWithTrigger((current) => !current)}
>
alignItemWithTrigger: {alignItemWithTrigger ? "true" : "false"}
</Button>
<Select defaultValue="Banana">
<SelectTrigger className="w-48">
<SelectValue />
</SelectTrigger>
<SelectContent alignItemWithTrigger={alignItemWithTrigger}>
<SelectGroup>
{fruits.map((fruit) => (
<SelectItem key={fruit} value={fruit}>
{fruit}
</SelectItem>
))}
</SelectGroup>
</SelectContent>
</Select>
</div>
)
}RTL
import {
Select,
SelectContent,
SelectGroup,
SelectItem,
SelectGroupLabel,
SelectSeparator,
SelectTrigger,
SelectValue,
} from "@/components/ui/select"
const fruits = ["سیب", "موز", "بلوبری"]
const vegetables = ["هویج", "بروکلی", "اسفناج"]
export function SelectRtlExample() {
return (
<Select>
<SelectTrigger className="w-40">
<SelectValue placeholder="یک میوه انتخاب کنید" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectGroupLabel>میوهها</SelectGroupLabel>
{fruits.map((fruit) => (
<SelectItem key={fruit} value={fruit}>
{fruit}
</SelectItem>
))}
</SelectGroup>
<SelectSeparator />
<SelectGroup>
<SelectGroupLabel>سبزیجات</SelectGroupLabel>
{vegetables.map((vegetable) => (
<SelectItem key={vegetable} value={vegetable}>
{vegetable}
</SelectItem>
))}
</SelectGroup>
</SelectContent>
</Select>
)
}Mixed direction
Base UI's SelectContent renders through a portal, so it doesn't inherit dir from a nearby wrapper — only from document.documentElement. This Select measures the ambient direction where its trigger actually renders and pushes it down, so each popup below follows its own local dir island correctly — even though both selects share the same page.
import {
Select,
SelectContent,
SelectGroup,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select"
export function SelectMixedDirectionExample() {
return (
<div className="flex flex-wrap items-start justify-center gap-8">
<div dir="ltr" className="flex flex-col gap-1.5">
<span className="text-xs text-muted-foreground">
dir="ltr" island
</span>
<Select defaultValue="Next.js">
<SelectTrigger className="w-40">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectItem value="Next.js">Next.js</SelectItem>
<SelectItem value="Remix">Remix</SelectItem>
<SelectItem value="Astro">Astro</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
</div>
<div dir="rtl" className="flex flex-col gap-1.5">
<span className="text-xs text-muted-foreground">
جزیرهی dir="rtl"
</span>
<Select defaultValue="نکستجیاس">
<SelectTrigger className="w-40">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectItem value="نکستجیاس">نکستجیاس</SelectItem>
<SelectItem value="ریمیکس">ریمیکس</SelectItem>
<SelectItem value="استرو">استرو</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
</div>
</div>
)
}API Reference
Select
| Prop | Type | Default | Description |
|---|---|---|---|
| items | Value[] | undefined | Data used to resolve a selected value's display label. Not required when items are already strings. |
| value | Value | undefined | The selected value. Use when controlled. |
| defaultValue | Value | undefined | The initially selected value when uncontrolled. |
| onValueChange | (value, details) => void | — | Called when the selected value changes. |
| multiple | boolean | false | Whether multiple items can be selected. |
| disabled | boolean | false | Prevents interaction with the select. |
| readOnly | boolean | false | Prevents choosing a different option from the popup. |
| required | boolean | false | Whether the user must choose a value before submitting a form. |
| name | string | undefined | Identifies the field when a form is submitted. |
SelectTrigger
| Prop | Type | Default | Description |
|---|---|---|---|
| disabled | boolean | false | Prevents interaction with the trigger. |
| aria-invalid | boolean | undefined | Marks the trigger as invalid for styling and assistive tech. |
SelectContent
| Prop | Type | Default | Description |
|---|---|---|---|
| sideOffset | number | 6 | Distance in pixels between the anchor and the popup. |
| align | "start" | "center" | "end" | "center" | How the popup is aligned relative to the trigger. |
| alignItemWithTrigger | boolean | true | When true, positions the popup so the selected item sits over the trigger. When false, aligns to the trigger's edge instead. |
SelectItem
| Prop | Type | Default | Description |
|---|---|---|---|
| value | Value | required | The value associated with this item. |
| disabled | boolean | false | Prevents selection of this item. |