# Select
URL: /design/components/select

A dropdown select component with composable sub-components.

> For AI agents: a documentation index is available at [llms.txt](/llms.txt). Use `.md` for canonical markdown pages; `.mdx` is kept as a backwards-compatible alias on supported URL paths.

\[interactive preview omitted]

## Installation

With the style-aware registry configured in components.json ("@assistant-ui": "https\://r.assistant-ui.com/styles/{style}/{name}.json"), the flavor resolves from the project style automatically:

```bash
npx shadcn@latest add @assistant-ui/select
```

Or add by direct URL without registry configuration:

```bash
npx shadcn@latest add https://r.assistant-ui.com/base/select.json
```

Or install manually:

```bash
npm install @base-ui/react
```

Then copy these files (packaged registry content; the source links show where each ships from):

- [components/ui/select.tsx](https://r.assistant-ui.com/base/files/select/components/ui/select.tsx) ([source](https://github.com/assistant-ui/assistant-ui/blob/main/packages/ui/src/components/react/ui/base/select.tsx))

```bash
curl -fsSL --create-dirs \
  -o 'components/ui/select.tsx' https://r.assistant-ui.com/base/files/select/components/ui/select.tsx
```

## Usage

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

const fruits = [
  { value: "apple", label: "Apple" },
  { value: "banana", label: "Banana" },
  { value: "orange", label: "Orange" },
];

export function FruitPicker() {
  return (
    <Select defaultValue="apple" items={fruits}>
      <SelectTrigger className="w-44">
        <SelectValue placeholder="Select a fruit..." />
      </SelectTrigger>
      <SelectContent>
        {fruits.map((fruit) => (
          <SelectItem key={fruit.value} value={fruit.value}>
            {fruit.label}
          </SelectItem>
        ))}
      </SelectContent>
    </Select>
  );
}
```

The Base UI flavor uses the `items` prop to resolve the selected label. Radix reads the label from the selected item, so the prop can be omitted there.

## Examples

### Sizes

Use the `size` prop on `SelectTrigger` to change the trigger height.

\[interactive preview omitted]

```
<SelectTrigger size="default" /> // 36px
<SelectTrigger size="sm" />      // 32px
```

### Scrollable

Long lists automatically become scrollable.

\[interactive preview component SelectScrollableSample omitted]

Code for SelectScrollableSample preview:

```tsx
"use client";

import { useState } from "react";
import {
  Select,
  SelectContent,
  SelectGroup,
  SelectItem,
  SelectLabel,
  SelectSeparator,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";

function SelectScrollableSample() {
  const [value, setValue] = useState("est");
  const items = timezoneGroups.flatMap((group) => group.items);

  return (
    <Select
      value={value}
      onValueChange={(nextValue) => nextValue !== null && setValue(nextValue)}
      items={items}
    >
      <SelectTrigger className="w-64">
        <SelectValue placeholder="Select a timezone..." />
      </SelectTrigger>
      <SelectContent>
        {timezoneGroups.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>
    </Select>
  );
}
```

### Groups

Group related items with `SelectGroup` and `SelectLabel`.

\[interactive preview component SelectGroupsSample omitted]

Code for SelectGroupsSample preview:

```tsx
"use client";

import { useState } from "react";
import {
  Select,
  SelectContent,
  SelectGroup,
  SelectItem,
  SelectLabel,
  SelectSeparator,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";

function SelectGroupsSample() {
  const [value, setValue] = useState("react");
  const items = [...frameworks, ...backends];

  return (
    <Select
      value={value}
      onValueChange={(nextValue) => nextValue !== null && setValue(nextValue)}
      items={items}
    >
      <SelectTrigger className="w-48">
        <SelectValue placeholder="Select a framework..." />
      </SelectTrigger>
      <SelectContent>
        <SelectGroup>
          <SelectLabel>Frontend</SelectLabel>
          {frameworks.map((item) => (
            <SelectItem key={item.value} value={item.value}>
              {item.label}
            </SelectItem>
          ))}
        </SelectGroup>
        <SelectSeparator />
        <SelectGroup>
          <SelectLabel>Backend</SelectLabel>
          {backends.map((item) => (
            <SelectItem key={item.value} value={item.value}>
              {item.label}
            </SelectItem>
          ))}
        </SelectGroup>
      </SelectContent>
    </Select>
  );
}
```

### Disabled items

\[interactive preview component SelectDisabledItemsSample omitted]

Code for SelectDisabledItemsSample preview:

```tsx
"use client";

import { useState } from "react";
import {
  Select,
  SelectContent,
  SelectGroup,
  SelectItem,
  SelectLabel,
  SelectSeparator,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";

function SelectDisabledItemsSample() {
  const [value, setValue] = useState("free");
  const plans = [
    { value: "free", label: "Free" },
    { value: "pro", label: "Pro" },
    { value: "enterprise", label: "Enterprise", disabled: true },
  ];

  return (
    <Select
      value={value}
      onValueChange={(nextValue) => nextValue !== null && setValue(nextValue)}
      items={plans}
    >
      <SelectTrigger className="w-44">
        <SelectValue />
      </SelectTrigger>
      <SelectContent>
        {plans.map((plan) => (
          <SelectItem
            key={plan.value}
            value={plan.value}
            disabled={plan.disabled === true}
          >
            {plan.label}
          </SelectItem>
        ))}
      </SelectContent>
    </Select>
  );
}
```

### With placeholder

\[interactive preview component SelectPlaceholderSample omitted]

Code for SelectPlaceholderSample preview:

```tsx
"use client";

import { useState } from "react";
import {
  Select,
  SelectContent,
  SelectGroup,
  SelectItem,
  SelectLabel,
  SelectSeparator,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";

function SelectPlaceholderSample() {
  const [value, setValue] = useState<string | null>(null);

  return (
    <Select value={value} onValueChange={setValue} items={fruits}>
      <SelectTrigger className="w-44">
        <SelectValue placeholder="Choose an option..." />
      </SelectTrigger>
      <SelectContent>
        {fruits.map((fruit) => (
          <SelectItem key={fruit.value} value={fruit.value}>
            {fruit.label}
          </SelectItem>
        ))}
      </SelectContent>
    </Select>
  );
}
```

### Disabled select

\[interactive preview component SelectDisabledSample omitted]

Code for SelectDisabledSample preview:

```tsx
"use client";

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

function SelectDisabledSample() {
  return (
    <Select value="apple" items={fruits} disabled>
      <SelectTrigger className="w-44">
        <SelectValue />
      </SelectTrigger>
      <SelectContent>
        {fruits.map((fruit) => (
          <SelectItem key={fruit.value} value={fruit.value}>
            {fruit.label}
          </SelectItem>
        ))}
      </SelectContent>
    </Select>
  );
}
```

## API Reference

### Composable API

| Component                | Description                                      |
| ------------------------ | ------------------------------------------------ |
| `Select`                 | The root component that manages selection state. |
| `SelectTrigger`          | The button that opens the dropdown.              |
| `SelectValue`            | The selected value or placeholder.               |
| `SelectContent`          | The dropdown content container.                  |
| `SelectItem`             | An individual selectable item.                   |
| `SelectGroup`            | A group of related items.                        |
| `SelectLabel`            | A label for a group.                             |
| `SelectSeparator`        | A visual separator between items or groups.      |
| `SelectScrollUpButton`   | The upward scroll control for long lists.        |
| `SelectScrollDownButton` | The downward scroll control for long lists.      |

### Select

- `defaultValue?`: `string` — The initial selected value for an uncontrolled select.
- `value?`: `string | null` — The controlled selected value.
- `onValueChange?`: `(value: string | null) => void` — Called when the selected value changes.
- `items?`: `Array<{ value: string; label: ReactNode; disabled?: boolean }>` — Base UI item metadata used to resolve labels and disabled state.
- `disabled?`: `boolean` — Whether the select is disabled.

### SelectTrigger

- `size`: `"sm" | "default"` (default `"default"`) — The trigger height.
- `className?`: `string` — Additional CSS classes.