A named set of checkboxes that answer one question together, such as which modes the map shows, holding the ticked values as one list, with a line of help and an error message tied to the set, submitted with a form under one name, and, where the set needs one, a parent checkbox that ticks or unticks them all.
When to use
Use CheckboxGroup for several answers to one question, applied when the form is sent, such as which modes a report covers, with a parent checkbox where the set needs one.
| Use instead | When |
|---|---|
| Checkbox | One setting or answer is on or off on its own |
| RadioGroup | The answer is one choice among two to six |
| SegmentedControl | The choice is one of two to five ways to show one view |
| FilterChip | The answers are filters on the map, which take effect at once |
| Fieldset | The group holds different controls, such as the fields of a report form, under one name |
Kongens Nytorv
Metro M1, M2 and M3.
The map shows vehicles of the ticked modes only
BusMetroS-togVariants and states
| Rest | Disabled | |
|---|---|---|
| Default | Show on map The map shows vehicles of the ticked modes only BusMetroS-tog | Show on map The map shows vehicles of the ticked modes only BusMetroS-tog |
- RestShow on map
The map shows vehicles of the ticked modes only
BusMetroS-tog - DisabledShow on map
The map shows vehicles of the ticked modes only
BusMetroS-tog
Props
| Name | Type | Default | Description |
|---|---|---|---|
label* | ReactNode | — | Required. The group's name, in sentence case, a few words or a short question, such as "Show on map": shown above the checkboxes, and the group's accessible name. |
hiddenLabel | boolean | false | Whether the label is heard but not seen. Use it where a heading right above already names the group for the eye, so the group keeps its name for the ear. |
description | ReactNode | — | A line of help under the label about the whole set, such as "The map shows vehicles of the ticked modes only", read after each checkbox's name by a screen reader. Left out, no description is rendered. |
error | ReactNode | — | What is wrong with the ticked set and how to put it right, such as "Choose at least one mode". Given, it marks the group invalid and is shown under the checkboxes; left out, the group shows Base UI's own message when its validate fails. |
onChange | (event: Event, value: string[], details: CheckboxGroup.ChangeEventDetails) => void | — | Called when a click or Space ticks or unticks a checkbox in the group, or a parent checkbox ticks or unticks the set, with the new list of ticked values as value; details.reason is 'none', and details.cancel() keeps the list as it was. event is details.event. Not called while disabled. |
disabled | boolean | false | Whether every checkbox in the group ignores the pointer and the keys. They leave the tab order and take the disabled look, with the label, the description and the error; a fieldset round the group disables it too. |
name | string | — | Identifies the group when a form is submitted: each ticked checkbox submits its value under this name, and a disabled one submits nothing. |
children* | ReactNode | — | Required. The group's checkboxes, in reading order: each a Checkbox with its own value, which the group's value lists while it is ticked, and, with allValues, a parent Checkbox first. |
className | string | — | Reaches the root, the group. Merged after pn-CheckboxGroup. |
style | CSSProperties | — | Reaches the root, the group. |
ref | Ref<HTMLElement> | — | Reaches the root, the group: the <div role="group">, or the element render gives. |
slotProps | { legend?: FieldsetLegendProps | undefined; description?: FieldDescriptionProps | undefined; error?: FieldErrorProps | undefined; } | — | Props for each part: legend, description, error. |
label (required)ReactNode, default —- Required. The group's name, in sentence case, a few words or a short question, such as "Show on map": shown above the checkboxes, and the group's accessible name.
hiddenLabelboolean, defaultfalse- Whether the label is heard but not seen. Use it where a heading right above already names the group for the eye, so the group keeps its name for the ear.
descriptionReactNode, default —- A line of help under the label about the whole set, such as "The map shows vehicles of the ticked modes only", read after each checkbox's name by a screen reader. Left out, no description is rendered.
errorReactNode, default —- What is wrong with the ticked set and how to put it right, such as "Choose at least one mode". Given, it marks the group invalid and is shown under the checkboxes; left out, the group shows Base UI's own message when its
validatefails. onChange(event: Event, value: string[], details: CheckboxGroup.ChangeEventDetails) => void, default —- Called when a click or Space ticks or unticks a checkbox in the group, or a parent checkbox ticks or unticks the set, with the new list of ticked values as
value;details.reasonis'none', anddetails.cancel()keeps the list as it was.eventisdetails.event. Not called while disabled. disabledboolean, defaultfalse- Whether every checkbox in the group ignores the pointer and the keys. They leave the tab order and take the disabled look, with the label, the description and the error; a fieldset round the group disables it too.
namestring, default —- Identifies the group when a form is submitted: each ticked checkbox submits its
valueunder this name, and a disabled one submits nothing. children (required)ReactNode, default —- Required. The group's checkboxes, in reading order: each a Checkbox with its own
value, which the group'svaluelists while it is ticked, and, withallValues, a parent Checkbox first. classNamestring, default —- Reaches the root, the group. Merged after
pn-CheckboxGroup. styleCSSProperties, default —- Reaches the root, the group.
refRef<HTMLElement>, default —- Reaches the root, the group: the
<div role="group">, or the elementrendergives. slotProps{ legend?: FieldsetLegendProps | undefined; description?: FieldDescriptionProps | undefined; error?: FieldErrorProps | undefined; }, default —- Props for each part:
legend,description,error.
Use it
import { CheckboxGroup } from '@mylder/perron'Ask your agent
get_reference({ library: "base-ui", component: "CheckboxGroup" })get_reference({ library: "base-ui", component: "Field" })Keyboard and ARIA
From the Base UI reference for CheckboxGroup, Field and Checkbox, the installed CheckboxGroup and CheckboxRoot, and Fieldset. "From" says who does it. The group adds no keys: each checkbox is a tab stop of its own, as on a native set of checkboxes, since each is an answer of its own, and no roving focus or arrow keys join them.
| Key | Does | From |
|---|---|---|
Tab, Shift+Tab | Moves to each checkbox in the group in reading order, and out of the group; skips them all while the group is disabled | The browser, and Base UI's tabIndex |
Space | Ticks or unticks the focused checkbox on release, adds its value to the group's list or takes it out, and calls onChange; on a parent checkbox, ticks or unticks the set, as a click does | Base UI, through Checkbox |
Enter | Doesn't toggle; in a form, clicks the form's default submit button | Base UI, through Checkbox |
| Element | Role | Accessible name from | States announced |
|---|---|---|---|
root | group, from Base UI's CheckboxGroup | aria-labelledby, the legend's id, from Fieldset and Base UI: its text | None on the group; it is described, through aria-describedby, by the description and the mounted error |
legend | None (generic div, or a span when hidden) | None: its text names the root | None |
description | None (paragraph) | None: its text describes the root and each checkbox | None |
checkbox | checkbox, from Checkbox | Its own label, its children, from Checkbox | aria-checked, a parent's mixed while some of the set is ticked; a parent's aria-controls, the ids of the boxes it controls; aria-disabled while the group is disabled; aria-invalid while the group is invalid; aria-describedby the description and error |
error | None (generic div, or Base UI's ul for several messages) | None: its text describes the root and each checkbox | None: it is read through aria-describedby, never as a live region |
What axe won't catch, from the contract, each with how this component meets it:
- Everything the eye is told, the ear is told, for every shape each prop accepts: the label the eye reads above the set is the group's name, and still is when hidden; the description and the error are the group's and each checkbox's description; each checkbox's tick is its
aria-checked, and a parent's dash itsaria-checked="mixed", witharia-controlsnaming the boxes it ticks; the danger edges of an invalid group are its error's words and each checkbox'saria-invalid; the tertiary colour of a disabled group is each checkbox'saria-disabled. - Every landmark and named region has an accessible name: the root is a
group, not a landmark, and is always named by its legend, sincelabelis required. - Every default label can be overridden: none here; CheckboxGroup owns no strings.
- Every shape the type accepts renders, in every variant:
label,descriptionanderroreach render a string, an element and a list alike, at rest, disabled and invalid;descriptionanderrorthat render nothing leave their part out, by thegivenhelper and by Base UI'sField.Errormounting only with a message. - A hidden copy kept for animation is
aria-hidden, and a collapsed region isinert: none here; nothing animates or collapses, and the error is unmounted, not hidden, while there is none. - Native semantics first: Base UI's
role="group"named througharia-labelledby, a<p>for the help, each checkbox Base UI'srole="checkbox"with its native hidden input; rendered as a<div>, not a<fieldset>, since Base UI's group renders the element, and Base UI's context, not the browser, disables the checkboxes (Fieldset's CR-5). - Focus moves in reading order and returns on close: the legend, the description, the checkboxes in the caller's order, a parent first, then the error, in the DOM and on screen; each checkbox, a parent among them, is one tab stop; the group never moves focus, and nothing in it closes.
- Every target is at least
size.target-minsquare: the group has no target of its own; each checkbox's row is its target, at leastsize.target-minsquare, from Checkbox's CR-9. - Loops stop when the system asks for less motion: none here; nothing moves.
Owned strings
No owned strings: every word the group shows or announces comes from the caller, through label, description, error, the validate messages and each checkbox's label, a parent's among them, and each checkbox's state is heard from aria-checked, in the screen reader's own words.
Do and don't
For a caller using the component, with the reason. Each row is a rule: a must row's Don't is never right, a should row's needs a reason, and Checked by says what catches the Don't in a caller's code.
| Rule | Level | Do | Don't | Checked by |
|---|---|---|---|---|
| DD-1 | should | Use CheckboxGroup for several answers to one question that are applied when the form is sent, such as which modes a report covers | Use it for filters on the map that take effect at once: those are FilterChips, pressed and seen at once | review |
| DD-2 | must | Give every checkbox a value of its own, and read and set the ticked set through the group's value and onChange | Give the checkboxes checked, defaultChecked or onChange of their own to keep the set: the group's value overrides them, and a box with no value takes the group's name | review |
| DD-3 | should | Write the legend in sentence case as the question the set answers, "Show on map", and each label as an answer, "Bus" | Repeat the legend's words in every label ("Show bus on map"): the screen reader reads the group's name before each box already | review |
| DD-4 | should | Give name so the ticked values reach the form, and connect a form library through its controller | Keep a hidden input of your own for the list: Base UI's hidden inputs already submit each ticked box | review |
| DD-5 | must | Say what is wrong in words, through error or a validate that returns the message, such as "Choose at least one mode" | Rely on the checkboxes' danger edges alone: colour is never the only sign (Accessibility) | review |
| DD-6 | must | Use description for help about the whole set, such as what ticking means | Put help or an error as plain text among the checkboxes: nothing ties it to the group for the ear | review |
| DD-7 | should | Disable the whole group with disabled, so every box goes together | Disable each box by hand in a group that stays enabled: the legend then looks live over dead boxes | review |
| DD-8 | must | Use a radio group or a SegmentedControl for one choice among several | Use a CheckboxGroup for one choice: a set of checkboxes says any number may be ticked, none included | review |
| DD-9 | must | Put a parent Checkbox, with parent and no value, first in the group and name it for the set, "All modes", and list every other checkbox's value in allValues | Leave a value out of allValues, or indent the boxes under the parent with a wrapper of your own: the parent counts only what allValues lists, and a wrapper takes the boxes out of the group's column | review |
| DD-10 | should | Use a single Checkbox for one on-or-off setting | Wrap one checkbox in a CheckboxGroup: a group of one adds a name the checkbox's own label already gives | review |