Skip to content
design system
Thème d’affichage, actuellement Auto

molecule · stable · extension · since 2026-09

StatusToggle

Purpose

The three statuses an auditor gives a criterion, as one button each in a named group: the retained one says so with aria-pressed, and each button carries the symbol of core next to the letter. “Non testé” is not offered: it is the absence of an answer.

When to use, when not

Use it wherever a criterion is judged in place: the rows of the panel, a criterion form. Not for a wizard’s question, which is AnswerButtons with Oui and Non; not to display a status, which is StatusChip.

Anatomy

  1. The group, named “Statut du critère 1.1”.
  2. One button per status, the symbol hidden, the letter visible, the word in the name.

Props

Props of StatusToggle
NameTypeDefaultWhat it does
criterionIdstringThe criterion's code, which names the group and each button: "Statut du critère 1.1".
value?StatutDeCritere | undefinedThe status retained; `NT` or absent leaves every button unpressed.
onchange(status: ChosenStatus) => voidCalled with the status pressed. Pressing the retained one calls it again; the caller decides whether that clears it.
statuses?ChosenStatus[]['C', 'NC', 'NA']The statuses offered, in order.
size?'sm' | 'md''sm'`sm` in a row of the panel, `md` in a form.
hooks?((status: ChosenStatus) => DataHooks) | undefinedThe `data-*` attributes of each button, from its status: what a click delegate or a walk reads.
class?string''Layout classes only.

States

Nothing pressed yet, one pressed, a reduced set, the form size, and the buttons carrying a consumer’s hooks.

hooked

The extension answers the buttons with a click delegate: each carries its data-action and the criterion, and the markup is otherwise the same.

Light

Critère 8.2 : pour chaque page web, le code source généré est-il valide ?

Dark

Critère 8.2 : pour chaque page web, le code source généré est-il valide ?

320 px, light

Critère 8.2 : pour chaque page web, le code source généré est-il valide ?

320 px, dark

Critère 8.2 : pour chaque page web, le code source généré est-il valide ?

216 px, light

Critère 8.2 : pour chaque page web, le code source généré est-il valide ?

Forced colours, captured
StatusToggle, story hooked, as Chromium renders it with forced colours active

medium

The size of a form, for a screen that holds one criterion.

Light

Critère 6.1 : chaque lien est-il explicite ?

Dark

Critère 6.1 : chaque lien est-il explicite ?

320 px, light

Critère 6.1 : chaque lien est-il explicite ?

320 px, dark

Critère 6.1 : chaque lien est-il explicite ?

216 px, light

Critère 6.1 : chaque lien est-il explicite ?

Forced colours, captured
StatusToggle, story medium, as Chromium renders it with forced colours active

pressed

Non conforme retained: the fill, the symbol and the letter say it together.

Light
Dark
320 px, light
320 px, dark
216 px, light
Forced colours, captured
StatusToggle, story pressed, as Chromium renders it with forced colours active

twoOnly

A criterion that cannot be non applicable: the group offers what the caller lists.

Light
Dark
320 px, light
320 px, dark
216 px, light
Forced colours, captured
StatusToggle, story twoOnly, as Chromium renders it with forced colours active

untested

No answer yet, under its criterion as in a row of the panel: every button unpressed. Press one; pressing it again calls the handler again and the story keeps it.

Light

Critère 1.1 : chaque image porteuse d’information a-t-elle une alternative textuelle ?

Dark

Critère 1.1 : chaque image porteuse d’information a-t-elle une alternative textuelle ?

320 px, light

Critère 1.1 : chaque image porteuse d’information a-t-elle une alternative textuelle ?

320 px, dark

Critère 1.1 : chaque image porteuse d’information a-t-elle une alternative textuelle ?

216 px, light

Critère 1.1 : chaque image porteuse d’information a-t-elle une alternative textuelle ?

Forced colours, captured
StatusToggle, story untested, as Chromium renders it with forced colours active

Accessibility contract

  • Role and name: a group named for the criterion; each button named “NC, Non conforme, critère 1.1” with aria-pressed.
  • Keyboard, focus: Tab reaches each button; Enter and Space press it; the focus stays on the button pressed, so the row can redraw in place.
  • Live regions: none; the pressed state is announced by the button itself. A row that also writes a note announces that elsewhere.

Content rules

French. The words are LIBELLES_DE_STATUT from core, never a copy; the shapes are the package’s status icons, drawn and hidden, never a text glyph, which would count in the visible label and be missing from the name. The group’s name is “Statut du critère” and the code.

Do and don’t

  • Do give the criterion’s code, always: three hundred groups named “Statut” are one group.
  • Do not add a fourth button for “non testé”; clearing an answer is a command of the row, if the product wants one.
  • Do not colour the letter at rest; the fill is for the pressed state only.
  • Do give hooks when a click delegate answers the buttons: hooks={() => ({ 'data-action': 'set-status', 'data-criterion-id': id })}. The component’s own data-status stays.

Examples

<StatusToggle criterionId={criterion.id} value={result?.status} onchange={(status) => setStatus(criterion.id, status)} />

Surfaces

  • Extension: every criterion row of the panel.

Related

CriterionRow, StatusChip, AnswerButtons.

Decisions

  • 2026-09-26: pressing the retained status calls the handler again rather than clearing it here: whether a second press clears the answer is the store’s rule, and the component does not keep a state of its own.
  • 2026-09-27: hooks hangs a consumer’s data-* attributes on each button, rather than the package naming the extension’s actions: the extension’s click delegate, its focus return and its walks read data-action="set-status" and the criterion, and the web app reads nothing. DataHooks admits data-* keys only, so no hook can change a name or a role.

Criteria held by construction

  • 3.1, Dans chaque page web, l'information ne doit pas être donnée uniquement par la couleur. Cette règle est-elle respectée ?
    The pressed status is told by aria-pressed, the symbol and the letter, and only then by the fill; the word is in the name.
  • 7.1, Chaque script est-il, si nécessaire, compatible avec les technologies d'assistance ?
    Native buttons with aria-pressed: the pressed state is the one assistive technology already knows, in a group named for the criterion.
  • 11.9, Dans chaque formulaire, l'intitulé de chaque bouton est-il pertinent ?
    The name of every button is explicit out of context: the letter, the word from core and the criterion.

Tokens it reads

  • Colour: --rl-c, --rl-hover, --rl-ink, --rl-ink-soft, --rl-line-control, --rl-line-strong, --rl-na, --rl-nc, --rl-on-fill, --rl-surface
  • Typography: --rl-weight-bold, --rl-text-base, --rl-text-sm
  • Spacing: --rl-space-1, --rl-space-1-5, --rl-space-3, --rl-space-half, --rl-target-min
  • Layout: --rl-radius, --rl-border

Seen in patterns