Select
Pick one option from a list, with the chosen item opening right over the trigger.
Installation
npx shadcn@latest add @quireui/selectUsage
const roles = [
{ value: "admin", label: "Admin" },
{ value: "member", label: "Member" },
];
<Select items={roles} defaultValue="member">
<SelectTrigger>
<SelectValue />
</SelectTrigger>
<SelectContent>
{roles.map((r) => (
<SelectItem key={r.value} value={r.value}>
{r.label}
</SelectItem>
))}
</SelectContent>
</Select>Pass items to Select so the trigger shows the label, not the raw value. It is the same list you render, so there is nothing extra to keep in sync.
Groups and long lists
Group options with SelectGroup and a SelectLabel, and divide groups with SelectSeparator. Anything after the label text in an item, like the offset below, sits on the right.
The open list places the chosen item right over the trigger, so the eye never has to jump. When the list is longer than the space around it, arrows appear at the top and bottom; hovering them scrolls. Pass alignItemWithTrigger={false} to open below the trigger instead.
In a form
Inside a Field with a name, the value is submitted with the form and required is validated like Input: the error appears under the field without moving anything below it.
<Form onFormSubmit={(values) => save(values.plan)}>
<Field name="plan">
<FieldLabel>Plan</FieldLabel>
<Select items={plans} required>
<SelectTrigger>
<SelectValue placeholder="Choose a plan" />
</SelectTrigger>
<SelectContent>{/* items */}</SelectContent>
</Select>
<FieldError />
</Field>
</Form>Sizes
size on Select: sm, md (default) or lg, the same heights as Button and Input, so a select sits flush in a toolbar or a form row. The open list follows the size too, so it still covers the trigger exactly. All three follow the density.
Accessibility
The trigger is read with its label and the chosen value. The list is a listbox, and the highlighted option is read as you move.
| Key | Action |
|---|---|
| Space / ↓ / ↑ | On the trigger: opens the list with the chosen item highlighted. |
| Letters | On the closed trigger: picks the next option starting with that letter, without opening. In the open list: jumps the highlight there. |
| ↓ / ↑ | Moves the highlight. |
| Home / End | Jumps to the first or last option. |
| Enter / Space | Picks the highlighted option and closes. |
| Esc | Closes without changing the value. |
| Tab | Closes and moves on, keeping the value. |
Enter does not open a closed select, the same as a native one, so pressing Enter in a form never opens a list by surprise.
Select or something else?
- Many options, or people search by name: Combobox filters as you type.
- Two to four options that should all stay visible: radio group or a segmented toggle group.
- Actions rather than a value: Dropdown menu.
API reference
Select
Prop
Type
Also takes every prop of Base UI's Select.Root.
SelectGroup
Also takes every prop of Base UI's Select.Group.
SelectTrigger
Also takes every prop of Base UI's Select.Trigger. Style it with [data-slot="select"].
SelectValue
The chosen item's label, or placeholder in a quieter colour until something is picked.
Also takes every prop of Base UI's Select.Value.
SelectContent
Also takes every prop of Base UI's Select.Popup. Style it with [data-slot="select-content"].
SelectItem
Also takes every prop of Base UI's Select.Item.
SelectLabel
Also takes every prop of Base UI's Select.GroupLabel.
SelectSeparator
Also takes every prop of Base UI's Select.Separator.