---
title: Select
description: A common form component for choosing a predefined value in a dropdown menu.
links:
  doc: https://base-ui.com/react/components/select
  anatomy: https://base-ui.com/react/components/select#anatomy
  api: https://base-ui.com/react/components/select#api-reference
---

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

const items = [
  { label: "Select a framework", value: null },
  { label: "Next.js", value: "next" },
  { label: "Tanstack start", value: "tanstack start" },
  { label: "Astro", value: "astro", disabled: true },
];

export function SelectDemo() {
  return (
    <Select items={items}>
      <SelectTrigger className="w-64">
        <SelectValue />
      </SelectTrigger>
      <SelectPopup>
        {items.map(({ label, value, disabled }) => (
          <SelectItem key={value} value={value} disabled={!!disabled}>
            {label}
          </SelectItem>
        ))}
      </SelectPopup>
    </Select>
  );
}
```

## Installation

<ComponentSource name="select" title="components/ui/select.tsx" />

## Usage

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

```tsx
<Select>
  <SelectTrigger className="w-45">
    <SelectValue />
  </SelectTrigger>
  <SelectPopup>
    <SelectItem value={null}>Theme</SelectItem>
    <SelectItem value="light">Light</SelectItem>
    <SelectItem value="dark">Dark</SelectItem>
    <SelectItem value="system">System</SelectItem>
  </SelectPopup>
</Select>
```

## Examples

### Sizes

Three sizes are available: `sm`, `md` (default) and `lg`.

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

const items = [
  { label: "Select a framework", value: null },
  { label: "Next.js", value: "next" },
  { label: "Tanstack start", value: "tanstack start" },
  { label: "Astro", value: "astro" },
];

export function SelectDemo() {
  return (
    <div className="flex flex-col gap-5">
      <Select items={items}>
        <SelectTrigger size="sm" className="w-64">
          <SelectValue />
        </SelectTrigger>
        <SelectPopup>
          {items.map(({ label, value }) => (
            <SelectItem key={value} value={value}>
              {label}
            </SelectItem>
          ))}
        </SelectPopup>
      </Select>
      <Select items={items}>
        <SelectTrigger className="w-64">
          <SelectValue />
        </SelectTrigger>
        <SelectPopup>
          {items.map(({ label, value }) => (
            <SelectItem key={value} value={value}>
              {label}
            </SelectItem>
          ))}
        </SelectPopup>
      </Select>
      <Select items={items}>
        <SelectTrigger size="lg" className="w-64">
          <SelectValue />
        </SelectTrigger>
        <SelectPopup>
          {items.map(({ label, value }) => (
            <SelectItem key={value} value={value}>
              {label}
            </SelectItem>
          ))}
        </SelectPopup>
      </Select>
    </div>
  );
}
```

### Disabled

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

const items = [
  { label: "Select a framework", value: null },
  { label: "Next.js", value: "next" },
  { label: "Tanstack start", value: "tanstack start" },
  { label: "Astro", value: "astro" },
];

export function SelectDemo() {
  return (
    <Select items={items} disabled>
      <SelectTrigger className="w-64">
        <SelectValue />
      </SelectTrigger>
      <SelectPopup>
        {items.map(({ label, value }) => (
          <SelectItem key={value} value={value}>
            {label}
          </SelectItem>
        ))}
      </SelectPopup>
    </Select>
  );
}
```

### Align item with trigger

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

const items = [
  { label: "Select a framework", value: null },
  { label: "Next.js", value: "next" },
  { label: "Tanstack start", value: "tanstack start" },
  { label: "Astro", value: "astro" },
];

export function SelectDemo() {
  return (
    <Select items={items}>
      <SelectTrigger className="w-64">
        <SelectValue />
      </SelectTrigger>
      <SelectPopup positionerProps={{ alignItemWithTrigger: true }}>
        {items.map(({ label, value }) => (
          <SelectItem key={value} value={value}>
            {label}
          </SelectItem>
        ))}
      </SelectPopup>
    </Select>
  );
}
```

### With groups

```tsx
import {
  Select,
  SelectGroup,
  SelectGroupLabel,
  SelectItem,
  SelectPopup,
  SelectSeparator,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";

const placeholder = [{ label: "Select framework", value: null }];

const frontend = [
  { label: "Next.js", value: "next" },
  { label: "Tanstack Start", value: "tanstack start" },
  { label: "Astro", value: "astro" },
];

const backend = [
  { label: "Express", value: "express" },
  { label: "NestJS", value: "nestjs" },
  { label: "Hono", value: "hono" },
  { label: "Elysia", value: "elysia" },
  { label: "Gin", value: "gin" },
  { label: ".NET", value: "dotnet" },
];

export function SelectDemo() {
  return (
    <Select aria-label="Select framework" items={[...placeholder, ...frontend, ...backend]}>
      <SelectTrigger className="w-64">
        <SelectValue />
      </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>
  );
}
```

### Multiple selection

Enable multiple selection by passing the `multiple` prop to the `Select` component.

```tsx
"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",
} as const;

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 function SelectDemo() {
  return (
    <Select aria-label="Select languages" defaultValue={["javascript", "typescript"]} multiple>
      <SelectTrigger className="w-64">
        <SelectValue>{renderValue}</SelectValue>
      </SelectTrigger>
      <SelectPopup>
        {values.map((value) => (
          <SelectItem key={value} value={value}>
            {languages[value]}
          </SelectItem>
        ))}
      </SelectPopup>
    </Select>
  );
}
```

### With icon

```tsx
import { IconClock } from "@tabler/icons-react";

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

const items = [
  { label: "Select time", value: null },
  { label: "Morning", value: "morning" },
  { label: "Afternoon", value: "afternoon" },
  { label: "Evening", value: "evening" },
  { label: "Night", value: "night" },
];

export function SelectDemo() {
  return (
    <Select items={items}>
      <SelectTrigger className="w-64">
        <IconClock />
        <SelectValue />
      </SelectTrigger>
      <SelectPopup>
        {items.map(({ label, value }) => (
          <SelectItem key={value} value={value}>
            {label}
          </SelectItem>
        ))}
      </SelectPopup>
    </Select>
  );
}
```

### With options icon

```tsx
"use client";

import {
  IconBrandAngular,
  IconBrandReact,
  IconBrandSolidjs,
  IconBrandVue,
  IconPackage,
} from "@tabler/icons-react";

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

const items = [
  { icon: IconPackage, label: "Select library", value: null },
  { icon: IconBrandReact, label: "React", value: "react" },
  { icon: IconBrandAngular, label: "Angular", value: "angular" },
  { icon: IconBrandSolidjs, label: "SolidJS", value: "solidjs" },
  { icon: IconBrandVue, label: "Vue", value: "vue" },
];

type Item = (typeof items)[number];

export function SelectDemo() {
  return (
    <Select
      aria-label="Select category"
      defaultValue={items[0]}
      itemToStringValue={(item) => (item as Item).value ?? ""}
    >
      <SelectTrigger className="w-64">
        <SelectValue>
          {(item: 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

```tsx
"use client";

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

const items = [
  { description: "Select project size", label: "Select size", value: null },
  { description: "Small size projects", label: "Small", value: "small" },
  { description: "Medium size projects", label: "Medium", value: "medium" },
  { description: "Large size projects", label: "Large", value: "large" },
  { description: "Enterprise size projects", label: "Enterprise", value: "enterprise" },
];

type Item = (typeof items)[number];

export function SelectDemo() {
  return (
    <Select
      aria-label="Select framework with command"
      defaultValue={items[0]}
      itemToStringValue={(item) => (item as Item).value ?? ""}
    >
      <SelectTrigger className="h-12 w-64">
        <SelectValue>
          {(item: 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>
  );
}
```

### With scrolling

By default, the Select component uses **built-in** scrollbars. You can also enable **native scrolling** by passing `nativeScroll` prop to the `SelectPopup` component.

```tsx
import {
  Select,
  SelectGroup,
  SelectGroupLabel,
  SelectItem,
  SelectPopup,
  SelectSeparator,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";

const placeholder = [{ label: "Select framework", value: null }];

const language = [
  { label: "JavaScript", value: "javascript" },
  { label: "TypeScript", value: "typescript" },
  { label: "Python", value: "python" },
  { label: "Go", value: "go" },
  { label: "C#", value: "csharp" },
  { label: "Ruby", value: "ruby" },
  { label: "Java", value: "java" },
  { label: "PHP", value: "php" },
];

const frontend = [
  { label: "Next.js", value: "next" },
  { label: "Tanstack Start", value: "tanstack start" },
  { label: "Astro", value: "astro" },
  { label: "React", value: "react" },
  { label: "Vue", value: "vue" },
  { label: "Svelte", value: "svelte" },
];

const backend = [
  { label: "Express", value: "express" },
  { label: "NestJS", value: "nestjs" },
  { label: "Hono", value: "hono" },
  { label: "Elysia", value: "elysia" },
  { label: "Gin", value: "gin" },
  { label: ".NET", value: "dotnet" },
  { label: "Django", value: "django" },
  { label: "Flask", value: "flask" },
  { label: "Spring", value: "spring" },
  { label: "Laravel", value: "laravel" },
];

export function SelectDemo() {
  return (
    <div className="flex flex-col gap-5">
      <div>
        <div className="mb-1">Built-in scrollbars (default):</div>
        <Select aria-label="Select tech stack" items={[...placeholder, ...frontend, ...backend]}>
          <SelectTrigger className="w-64">
            <SelectValue />
          </SelectTrigger>
          <SelectPopup>
            <SelectGroup>
              <SelectGroupLabel>Language</SelectGroupLabel>
              {language.map(({ label, value }) => (
                <SelectItem key={value} value={value}>
                  {label}
                </SelectItem>
              ))}
            </SelectGroup>
            <SelectSeparator />
            <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>
      </div>
      <div>
        <div className="mb-1">Native scrollbars:</div>
        <Select aria-label="Select tech stack" items={[...placeholder, ...frontend, ...backend]}>
          <SelectTrigger className="w-64">
            <SelectValue />
          </SelectTrigger>
          <SelectPopup nativeScroll>
            <SelectGroup>
              <SelectGroupLabel>Language</SelectGroupLabel>
              {language.map(({ label, value }) => (
                <SelectItem key={value} value={value}>
                  {label}
                </SelectItem>
              ))}
            </SelectGroup>
            <SelectSeparator />
            <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>
      </div>
    </div>
  );
}
```

### Controlled

```tsx
"use client";

import { useState } from "react";

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

const items = [
  { label: "Select a framework", value: null },
  { label: "Next.js", value: "next" },
  { label: "Tanstack start", value: "tanstack start" },
  { label: "Astro", value: "astro" },
];

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

  return (
    <div className="flex flex-col gap-5">
      <Select
        items={items}
        value={value}
        onValueChange={(value) => setValue(value as string | null)}
      >
        <SelectTrigger className="w-64">
          <SelectValue />
        </SelectTrigger>
        <SelectPopup>
          {items.map(({ label, value }) => (
            <SelectItem key={value} value={value}>
              {label}
            </SelectItem>
          ))}
        </SelectPopup>
      </Select>
      <div>Selected value: {value ?? "null"}</div>
    </div>
  );
}
```
