atom · stable · since 2026-09
Select
Purpose
A choice among options, as the native select and nothing else. The browser gives the focus, the arrows, typing the first letters, the system’s picker on a phone; a remade select loses all of it. The component ties the label, the hint and the error, and keeps an empty option so nothing chosen stays distinct from a choice.
When to use, when not
Use it for a choice among many options, or among a few that need no comparing. For two to five options the user should see at once, RadioGroup. For free text, Field.
Anatomy
- The label, with the required mark when needed.
- The hint.
- The select, with the empty option first, the options or the groups.
- The error.
Props
| Name | Type | Default | What it does |
|---|---|---|---|
id | string | The control's id; the label's `for` is the same value. | |
label | string | The visible label, a noun. | |
name? | string | The name sent with the form. | |
value? | string | undefined | The chosen value; bindable, absent reads as nothing chosen. | |
options? | Option[] | [] | The options, when they are not grouped. |
groups? | Group[] | [] | The options by group. |
placeholder? | string | 'Choisissez' | The text of the empty option, "Choisissez" by default; an empty string removes it. |
hint? | string | undefined | A help sentence, announced with the field. | |
error? | string | undefined | The error message; its presence alone marks the field invalid. | |
required? | boolean | false | Required: the word goes into the accessible name and the attribute onto the control. |
disabled? | boolean | false | Unavailable. |
States
Plain, with a choice made, grouped, required, in error, and unavailable.
chosen
Light
Le niveau change le nombre de critères évalués.
Dark
Le niveau change le nombre de critères évalués.
320 px, light
Le niveau change le nombre de critères évalués.
320 px, dark
Le niveau change le nombre de critères évalués.
216 px, light
Forced colours, captured

disabled
Light
Une seule version est prise en charge.
Dark
Une seule version est prise en charge.
320 px, light
Une seule version est prise en charge.
320 px, dark
Une seule version est prise en charge.
216 px, light
Forced colours, captured

error
aria-invalid on the select, the message tied by aria-describedby and read as an alert.
Light
Choisissez la fréquence des audits.
Dark
Choisissez la fréquence des audits.
320 px, light
Choisissez la fréquence des audits.
320 px, dark
Choisissez la fréquence des audits.
216 px, light
Forced colours, captured

grouped
optgroup: the group label is read before its options, and the position is counted inside the whole list.
Light
Dark
320 px, light
320 px, dark
216 px, light
Forced colours, captured

plain
Light
Dark
320 px, light
320 px, dark
216 px, light
Forced colours, captured

required
Light
Dark
320 px, light
320 px, dark
216 px, light
Forced colours, captured

Accessibility contract
- Role and name: a listbox in a combobox, as the browser exposes a select, named by its label; “(obligatoire)” in the name when required.
- Keyboard, focus: the browser’s. No navigation on change: the arrows walk the options one by one, and a navigation fired there would leave on the first one met.
- Live regions: the error is
role="alert".
Content rules
French. The label is a noun (“Niveau visé”); the empty option says what to do (“Choisissez”, “Choisissez un critère”); option texts are short and start with what distinguishes them.
Do and don’t
- Do keep the empty option unless a value is always chosen, as with a single supported version.
- Do not navigate or submit on change.
- Do not remake the control with a list of divs.
Examples
<Select id="level" label="Niveau visé" options={levels} bind:value={level} required />
<Select id="criterion" label="Critère" groups={byTheme} placeholder="Choisissez un critère" /> Surfaces
- App: the audit’s method and version, the new account’s role.
- Extension: the page switcher’s list, when the panel is on Svelte.
Related
Field, RadioGroup.
Decisions
- 2026-09-24:
placeholderdefaults to “Choisissez” and an empty string removes it, so the ordinary case asks and the exception is written.
Criteria held by construction
- 11.1, Chaque champ de formulaire a-t-il une étiquette ?
The label's for and the control's id come from one prop, so a select cannot be rendered without its label. - 11.10, Dans chaque formulaire, le contrôle de saisie est-il utilisé de manière pertinente ?
The error is tied by aria-describedby and aria-invalid together, and an empty option keeps nothing chosen distinct from a choice. - 7.3, Chaque script est-il contrôlable par le clavier et par tout dispositif de pointage ?
The native element gives the arrows, the first letters and the system's picker; nothing is remade, so nothing is lost.
Tokens it reads
- Colour:
--rl-action,--rl-ink,--rl-ink-soft,--rl-line,--rl-line-control,--rl-nc,--rl-surface - Typography:
--rl-weight-bold,--rl-text-base,--rl-text-sm - Spacing:
--rl-space-1-5,--rl-space-2,--rl-space-3 - Layout:
--rl-radius,--rl-border