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

CreditsModifiedPublished

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.json

Usage

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.

dir="ltr" island
جزیره‌ی dir="rtl"
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=&quot;ltr&quot; 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=&quot;rtl&quot;
        </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

PropTypeDefaultDescription
itemsValue[]undefinedData used to resolve a selected value's display label. Not required when items are already strings.
valueValueundefinedThe selected value. Use when controlled.
defaultValueValueundefinedThe initially selected value when uncontrolled.
onValueChange(value, details) => voidCalled when the selected value changes.
multiplebooleanfalseWhether multiple items can be selected.
disabledbooleanfalsePrevents interaction with the select.
readOnlybooleanfalsePrevents choosing a different option from the popup.
requiredbooleanfalseWhether the user must choose a value before submitting a form.
namestringundefinedIdentifies the field when a form is submitted.

SelectTrigger

PropTypeDefaultDescription
disabledbooleanfalsePrevents interaction with the trigger.
aria-invalidbooleanundefinedMarks the trigger as invalid for styling and assistive tech.

SelectContent

PropTypeDefaultDescription
sideOffsetnumber6Distance in pixels between the anchor and the popup.
align"start" | "center" | "end""center"How the popup is aligned relative to the trigger.
alignItemWithTriggerbooleantrueWhen true, positions the popup so the selected item sits over the trigger. When false, aligns to the trigger's edge instead.

SelectItem

PropTypeDefaultDescription
valueValuerequiredThe value associated with this item.
disabledbooleanfalsePrevents selection of this item.