molecule · stable · app · since 2026-09
FilterGroup
Purpose
A row of filters that apply the moment they are pressed: a group named by a visible label, one button per filter with aria-pressed, several pressed at once or one alone when exclusive. No form, no “Appliquer”; the page says the count through its live region.
When to use, when not
Use it above a list for two to six filters the user sees at once. Use a RadioGroup when the filters are part of a form submitted later, a Select when there are more than six. Not for navigation between pages, which is a list of links.
Anatomy
- The visible label.
- The buttons, each with its word and its count when given.
Props
| Name | Type | Default | What it does |
|---|---|---|---|
label | string | The visible label that names the group: "Statut", "Niveau". | |
filters | Filter[] | The filters, in order. With `exclusive`, the first one is the one that shows everything. | |
selected? | string[] | [] | The values pressed; bindable. |
exclusive? | boolean | false | One filter at a time, and one always pressed. |
onchange? | (selected: string[]) => void | Called with the values pressed after each press. | |
class? | string | '' | Layout classes only. |
States
Exclusive with “Tous” first, and several at once.
exclusive
One filter at a time, "Tous" first: pressing the pressed one changes nothing, so the list is never filtered by nothing.
Light
Dark
320 px, light
320 px, dark
216 px, light
Forced colours, captured
several
Several filters at once, none pressed at first; a press toggles, and the count is said by the page.
Light
Dark
320 px, light
320 px, dark
216 px, light
Forced colours, captured
Accessibility contract
- Role and name: a
groupnamed by the label througharia-labelledby; each button named by its word, witharia-pressed. - Keyboard, focus: Tab reaches each button; Enter and Space press it; the focus never moves on a press.
- Live regions: none of the group’s. The page says the count of the filtered list through LiveRegion, present from the first render.
Content rules
French. The label is a noun (“Statut”, “Thématiques”); the filters are nouns or participles in the plural (“Terminés”, “Brouillons”); the first exclusive filter is “Tous”.
Do and don’t
- Do announce the count after a press, in a sentence: “5 audits affichés”.
- Do list “Tous” first when exclusive, so the list is never filtered by nothing.
- Do not move the focus to the list on a press; the user is still choosing.
Examples
<FilterGroup label="Statut" filters={STATUSES} exclusive bind:selected={status} onchange={refilter} />
<LiveRegion message={count} visible /> Surfaces
- App: the audits list, the users list.
Related
RadioGroup, Select, LiveRegion, Chip.
Decisions
- 2026-09-26: buttons with
aria-pressedand not radios: the filters apply at once, and a radio group promises a form. - 2026-09-26: an exclusive group refuses to unpress its last filter: a list filtered by nothing is the whole list, which “Tous” already says.
Criteria held by construction
- 7.1, Chaque script est-il, si nécessaire, compatible avec les technologies d'assistance ?
Native buttons with aria-pressed in a group named by its visible label: the state and the group are the ones assistive technology knows. - 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 ?
A pressed filter is told by aria-pressed and the fill with the bold, not by a hue on an outline. - 11.1, Chaque champ de formulaire a-t-il une étiquette ?
The group's label is visible and tied by aria-labelledby, so the filters are heard as 'Statut, groupe'.
Tokens it reads
- Colour:
--rl-hover,--rl-ink,--rl-line-control,--rl-line-strong,--rl-on-fill - Typography:
--rl-weight-bold,--rl-text-sm,--rl-text-xs - Spacing:
--rl-space-1,--rl-space-1-5,--rl-space-2,--rl-space-3,--rl-target-min - Layout:
--rl-radius,--rl-border