Select
Usage
Use a select to pick one option from a known list of about 5–15 items — depot, service type, vehicle class. Use radios for 2–5 options people should compare, and a combobox when the list is long or people know what they are looking for (a part number, one of 400 vehicles).
- Start with a prompt option ("Choose a depot",
value="") unless there is a safe default. - Group long lists with
optgroup; order options alphabetically or by frequency. - It's a native
<select>: the OS picker works with touch, screen readers and gloves.
Anatomy
- Wrapper —
.select, draws the chevron (::after, maskedcurrentColor) - Control — native
select.select__control, same border, radius and heights as the text field - Value or prompt option
- Picker — the OS list, or a token-styled
::picker(select)where customizable select is supported
Examples
Hover and focus-visible are frozen with .is-hover and .is-focus-visible, which share their rules with the real pseudo-classes.
Select
Vehicles can't change depot while a work order is open.
Set by the leasing contract.
Error: Select the depot where the vehicle parks overnight.
<div class="select [select--sm | select--lg]">
<select class="select__control" id="depot" name="depot" required>
<option value="">Choose a depot</option>
<option>North Yard</option>
<optgroup label="Preventive">…</optgroup>
</select>
</div>
<!-- States -->
<select class="select__control" … disabled>
<select class="select__control" … aria-invalid="true" aria-describedby="depot-error">
<!-- Read-only: <select> has no readonly; render only the current option -->
<select class="select__control" … aria-readonly="true"><option selected>Airport Logistics Park</option></select>
API
| Hook | Values | Purpose |
|---|---|---|
.select + .select__control | block / part | Wrapper with chevron + native select |
.select--sm | --lg | modifier class | 32 / 40 (default) / 48px — same as inputs and buttons |
disabled, required | attribute | Native states |
aria-invalid="true", :user-invalid | attribute / pseudo-class | Invalid |
aria-readonly="true" + one option | attribute | Read-only (focusable, submitted, no chevron) |
option[value=""] | markup | Prompt option, shown muted while selected |
.is-hover | .is-focus-visible | docs-only class | Freezes a state |
Do and don't
Accessibility
| Key | Behavior |
|---|---|
| Tab | Focuses the select |
| Space / Enter / Alt+↓ | Opens the picker |
| ↑ ↓, typing | Moves between options / jumps by first letters |
| Esc | Closes the picker without changing the value |
- Role: native
combobox/listbox(by platform) — all keyboard and screen-reader behavior is native. - The chevron is decorative (on the wrapper) and uses
currentColor, so it follows themes and forced colors. - Invalid: thicker red border, icon and message, linked with
aria-describedby. - Read-only keeps the value focusable and announced; only one option is rendered so it can't be changed.
Tokens
| Custom property | Purpose |
|---|---|
--input-border, --input-bg, --input-radius | Shared with text field |
--size-control-sm | -md | -lg | Heights |
--color-text-muted | Chevron, prompt option |
--color-border-focus, --focus-ring-*, --color-border-invalid | Focus, invalid |
--color-bg-overlay, --overlay-radius, --overlay-shadow, --color-selected-* | Customizable picker |