Select

Displays a list of options for the user to pick from, triggered by a button.

View as Markdown
const items = [  { label: "Select a fruit", value: null },  { label: "Apple", value: "apple" },  { label: "Banana", value: "banana" },];
<Select items={items}>  <SelectTrigger>    <SelectValue />  </SelectTrigger>  <SelectContent>    <SelectGroup>      <SelectLabel>Fruits</SelectLabel>      <SelectItem value="apple">Apple</SelectItem>      <SelectItem value="banana">Banana</SelectItem>    </SelectGroup>  </SelectContent></Select>;

Installation

$ npx shadcn@latest add @constella/select

Usage

import {  Select,  SelectContent,  SelectGroup,  SelectItem,  SelectTrigger,  SelectValue,} from "@/components/primitives/select";

Pass items to Select, so SelectValue shows the picked item's label. An item with value: null is the placeholder.

<Select items={items}>  <SelectTrigger>    <SelectValue />  </SelectTrigger>  <SelectContent>    <SelectItem value="light">Light</SelectItem>    <SelectItem value="dark">Dark</SelectItem>  </SelectContent></Select>

Composition

Select├── SelectTrigger│   └── SelectValue└── SelectContent    ├── SelectGroup    │   ├── SelectLabel    │   └── SelectItem    └── SelectSeparator

Align Item With Trigger

Use alignItemWithTrigger on SelectContent to choose where the popup opens. When false (default), the popup opens below the trigger, like a dropdown menu. When true, the selected item sits over the trigger.

Toggle to align the item with the trigger.

<SelectContent alignItemWithTrigger>  <SelectItem value="apple">Apple</SelectItem></SelectContent>

Groups

Use SelectGroup, SelectLabel and SelectSeparator to organize items.

<SelectContent>  <SelectGroup>    <SelectLabel>Fruits</SelectLabel>    <SelectItem value="apple">Apple</SelectItem>  </SelectGroup>  <SelectSeparator />  <SelectGroup>    <SelectLabel>Vegetables</SelectLabel>    <SelectItem value="carrot">Carrot</SelectItem>  </SelectGroup></SelectContent>

Scrollable

A long list scrolls, with arrows at the ends while there's more to see.

<SelectContent>  {timezones.map((group) => (    <SelectGroup key={group.label}>      <SelectLabel>{group.label}</SelectLabel>      {group.items.map((item) => (        <SelectItem key={item.value} value={item.value}>          {item.label}        </SelectItem>      ))}    </SelectGroup>  ))}</SelectContent>

Size

Use the size prop on SelectTrigger to match the controls beside it, and on SelectContent to size its rows.

SizeTriggerRowTextIcon
sm28px24px12px14px
default32px28px13px16px
lg36px32px13px16px
<SelectTrigger size="sm">  <SelectValue /></SelectTrigger><SelectContent size="sm">  <SelectItem value="apple">Apple</SelectItem></SelectContent>

Disabled

Add disabled to Select to disable it, or to a SelectItem to disable one option.

<Select disabled items={items}>  <SelectTrigger>    <SelectValue />  </SelectTrigger>  <SelectContent>    <SelectItem disabled value="grapes">      Grapes    </SelectItem>  </SelectContent></Select>

Invalid

Add invalid to the Field, so the trigger takes the red edge.

Please select a fruit.

<Field invalid>  <FieldLabel>Fruit</FieldLabel>  <Select items={items}>    <SelectTrigger>      <SelectValue />    </SelectTrigger>    <SelectContent>      <SelectItem value="apple">Apple</SelectItem>    </SelectContent>  </Select>  <FieldDescription>Please select a fruit.</FieldDescription></Field>

API Reference

PartAdds
SelectTriggersize: "sm", "default" or "lg"
SelectContentRenders the portal, positioner and popup; takes side, align, alignItemWithTrigger and their offsets; size: "sm", "default" or "lg" rows

Every part takes sx, applied last. For the rest, see Base UI Select.