Select

A dropdown to pick one value from a list, with groups, descriptions and form support.

Country
import { Select, SelectContent, SelectItem, SelectLabel, SelectTrigger } from "@hel/ui/select"
import { Stack } from "@hel/ui/stack"

When to use it

Use a select when people choose one value from a list that is too long to show all at once: a country, a time zone, a role. For two to five options that people should compare at a glance, a Radio Group is easier to use. If the list is long enough that people need to type to find an item, use a Combobox.

Import

import {
  Select,
  SelectTrigger,
  SelectContent,
  SelectItem,
  SelectGroup,
  SelectGroupLabel,
  SelectLabel,
  SelectSeparator,
} from "@hel/ui/select"

Anatomy

Select is a set of small parts, and you put them together. Select holds the value. SelectTrigger is the button that shows it. SelectContent is the popup, and it holds the SelectItem rows.

<Select items={COUNTRIES} defaultValue="iq">
  <SelectLabel>Country</SelectLabel>
  <SelectTrigger placeholder="Choose a country" />
  <SelectContent>
    {COUNTRIES.map((country) => (
      <SelectItem key={country.value} value={country.value} label={country.label} />
    ))}
  </SelectContent>
</Select>

Pass the list to Select as items as well. The trigger uses it to show the label of the chosen item, such as "United Arab Emirates", instead of its value, "ae". It also makes the label show on the first render, before the popup has ever been opened.

SelectLabel names the select for assistive technology, and it is also the visible label. placeholder on the trigger is shown while nothing is chosen.

Examples

Descriptions

Each item takes a label and an optional description, which is a good place for the difference between two similar choices. A disabled item stays visible but cannot be chosen.

Role
import { Select, SelectContent, SelectItem, SelectLabel, SelectTrigger } from "@hel/ui/select"
import { Stack } from "@hel/ui/stack"

Groups and separators

Use SelectGroup with a SelectGroupLabel to put a heading over a part of the list, and SelectSeparator to draw a line between parts.

Time zone
import {
  Select,
  SelectContent,

In a form

Give the select a name and the chosen value is submitted with the form. required makes the form wait for a choice.

By default the popup opens over the trigger with the chosen item in place, the way menus on macOS do. Set alignItemWithTrigger={false} on SelectContent to open it below the trigger like an ordinary menu. That suits long lists and triggers that are close to the edge of the screen.

Priority
import * as React from "react"

import { Button } from "@hel/ui/button"

Long lists

When the list is taller than the screen allows, SelectContent scrolls inside the same scroll area as the rest of the library.

Motion

The popup fades in and out, and the trigger gives a small press effect. Set disableAnimation on SelectContent or SelectTrigger to turn that off.

Props

Select

PropTypeDefault
items{ value, label }[]none
value / defaultValuethe item valuenone
onValueChange(value) => voidnone
multiplebooleanfalse
namestringnone
disabled / readOnly / requiredbooleanfalse

It also takes every prop of the Base UI select.

SelectTrigger

PropTypeDefault
placeholderReactNodenone
disableAnimationbooleanfalse

SelectContent

PropTypeDefault
alignItemWithTriggerbooleantrue
sideOffsetnumber4
align"start" | "center" | "end""start"
disableAnimationbooleanfalse

SelectItem

PropTypeDefault
valuestringrequired
labelReactNoderequired
descriptionReactNodenone
disabledbooleanfalse