Checkbox Group
import { CheckboxGroup } from '@absoluteui/components/checkbox-group';import '@absoluteui/components/checkbox-group/style.css';Using Angular? See Checkbox Group for Angular.
What it does
Section titled “What it does”Several related, independent choices. CheckboxGroup renders a <fieldset> and <legend> around native checkboxes that share one field name, with group help text, required and minSelected/maxSelected validation, and one localized validation message for the group. Checkboxes use the same visuals as Checkbox.
When to use
Section titled “When to use”- Choosing any number of options from a short, visible list (roughly 2 to 10).
- Selections with a minimum or maximum count, such as “pick up to three topics”.
When not to use
Section titled “When not to use”- Exactly one choice: use Radio Group.
- Long or searchable lists: use a multi-select Combobox or Listbox.
- A single yes/no choice: use Checkbox.
Examples
Section titled “Examples”Required group with help text
Section titled “Required group with help text”import { CheckboxGroup } from '@absoluteui/components/checkbox-group';
const host = document.createElement('div');document.body.append(host);CheckboxGroup.create(host, { label: 'Notifications', name: 'notify', description: 'Choose at least one channel.', required: true, options: [ { value: 'email', label: 'Email' }, { value: 'sms', label: 'SMS', description: 'Carrier rates may apply' }, { value: 'push', label: 'Push notification' }, ],});Selection limits, horizontal layout
Section titled “Selection limits, horizontal layout”import { CheckboxGroup } from '@absoluteui/components/checkbox-group';
const host = document.createElement('div');document.body.append(host);const topics = CheckboxGroup.create(host, { label: 'Topics', orientation: 'horizontal', minSelected: 2, maxSelected: 3, options: ['Design', 'Security', 'Performance', 'Accessibility'].map((t) => ({ value: t.toLowerCase(), label: t })),});host.addEventListener('aui-change', () => { host.dataset.count = String(topics.value.length);});Show messages on first change (Mode B)
Section titled “Show messages on first change (Mode B)”import { configureAbsoluteUI } from '@absoluteui/core';
configureAbsoluteUI({ components: { checkboxGroup: { validationTiming: 'input' } } });import { CheckboxGroup } from '@absoluteui/components/checkbox-group';import '@absoluteui/components/checkbox-group/style.css';
const host = document.querySelector<HTMLElement>('#topics');if (host) { const topics = CheckboxGroup.create(host, { label: 'Topics', maxSelected: 3, options: [ { value: 'design', label: 'Design' }, { value: 'security', label: 'Security' }, { value: 'performance', label: 'Performance' }, { value: 'a11y', label: 'Accessibility' }, ], }); host.addEventListener('aui-change', () => { host.dataset.count = String(topics.value.length); });}More usage
Section titled “More usage”import { CheckboxGroup } from '@absoluteui/components/checkbox-group';
const host = document.createElement('div');document.body.append(host);CheckboxGroup.create(host, { label: 'Notifications', name: 'notify', required: true, options: [ { value: 'email', label: 'Email' }, { value: 'sms', label: 'SMS' }, ],});Anatomy
Section titled “Anatomy”<div class="aui-field aui-checkbox-group" data-aui-control> (consumer host) <fieldset class="aui-checkbox-group__fieldset" aria-describedby> <legend class="aui-field__label">Label<span class="aui-field__required" aria-hidden="true">*</span><span class="aui-visually-hidden"> (required)</span></legend> <div class="aui-field__description"> (optional) <div class="aui-checkbox-group__options"> <div class="aui-checkbox-group__option"> (per option) <span class="aui-checkbox-group__box"> <input type="checkbox" class="aui-checkbox-group__input" name value> <span class="aui-checkbox-group__mark"><svg aria-hidden="true"></span> </span> <div class="aui-checkbox-group__text"> <label class="aui-checkbox-group__label" for=input> <div class="aui-checkbox-group__option-description"> (optional) </div> </div> </div> <div class="aui-field__error aui-validation-message"> (when shown) </fieldset></div>API reference
Section titled “API reference”Factory
Section titled “Factory”CheckboxGroup.create(host: HTMLElement, options: CheckboxGroupOptions): CheckboxGroupGlobal configuration key: checkboxGroup (see Configuration).
Options
Section titled “Options”| Option | Type | Default | Description |
|---|---|---|---|
label |
string |
Legend text and accessible name of the group. Required. | |
hideLabel |
boolean |
false |
Visually hide the legend; it remains the accessible name. |
options |
readonly { value: string; label: string; description?: string; disabled?: boolean }[] |
Choices; values must be unique. Required. | |
value |
readonly string[] |
"[]" |
Initially selected values; also restored by reset(). |
name |
string |
Form field name shared by every checkbox. | |
description |
string |
Group help text referenced by the fieldset’s aria-describedby. | |
required |
boolean |
false |
At least one option must be selected. |
minSelected |
number |
Minimum selections once any option is selected (integer 1..options.length). | |
maxSelected |
number |
Maximum selections (integer 1..options.length). | |
orientation |
'vertical' | 'horizontal' |
"vertical" |
Layout of the options. |
disabled |
boolean |
false |
Disables the whole group (fieldset disabled). |
validate |
(value: string[]) => string | null |
Consumer validation; return a message to mark the selection invalid. | |
icons |
Partial<{ checked: IconRef; error: IconRef }> |
Icon slot overrides. | |
validationTiming |
'blur' | 'input' | 'submit' |
"blur" |
When validation messages first appear; afterwards they update live. Globally configurable. |
locale |
string |
"en-US" |
Message and number-formatting locale. Globally configurable. Inherited from common configuration. |
Properties
Section titled “Properties”| Property | Type | Description |
|---|---|---|
host |
HTMLElement |
Consumer host; its children are owned by the component. |
fieldset |
HTMLFieldSetElement |
The grouping fieldset. |
inputs |
HTMLInputElement[] |
The native checkboxes, in option order. |
value |
string[] |
Selected values, in option order. |
name |
string | null |
Form field name. |
label |
string |
Legend text. |
disabled |
boolean |
Group disabled state. |
validity |
FieldValidity |
{ valid, error, message }; computed on every change. |
dirty |
boolean |
Selection differs from the initial selection. |
touched |
boolean |
Focus has left the group at least once. |
options |
Readonly<CheckboxGroupOptions> |
Current instance options. |
Methods
Section titled “Methods”| Method | Description |
|---|---|
setValue(value: readonly string[]): void |
Programmatic selection (no events); unknown values throw CHECKBOX_GROUP_OPTIONS. |
update(options: Partial<CheckboxGroupOptions>): void |
Merge and apply options; a new option list keeps selections that still exist. |
reportValidity(): boolean |
Show messages now and return validity. |
setCustomError(message: string | null): void |
External error; cleared when the selection changes. |
getFormValue(): string[] |
Selected values for form serialization. |
focus(): void |
Focus the first enabled checkbox. |
reset(): void |
Restore the initial selection and clear dirty/touched/submitted state. |
destroy(): void |
Remove rendering, listeners, registration, and subscriptions. |
Events
Section titled “Events”| Event | Detail | Bubbles | Cancelable | Description |
|---|---|---|---|---|
aui-change |
{ value: string[]; validity: FieldValidity } |
Yes | No | The user toggled an option. |
CSS classes
Section titled “CSS classes”All rules live in the aui.components cascade layer, so application styles override them without specificity battles.
| Class | Purpose |
|---|---|
aui-field aui-checkbox-group |
Host. |
aui-checkbox-group--invalid | --disabled |
State modifiers on the host. |
aui-field__label | __required | __description | __error |
Shared field chrome (the label is the legend). |
aui-checkbox-group__fieldset |
Grouping fieldset. |
aui-checkbox-group__options | __options--horizontal |
Option list and its horizontal layout. |
aui-checkbox-group__option |
One option row. |
aui-checkbox-group__box | __input | __mark |
Checkbox box, native input, and check mark. |
aui-checkbox-group__text | __label | __option-description |
Option label and help text. |
Icon slots
Section titled “Icon slots”| Slot | Default icon |
|---|---|
checked |
check |
error |
alert-circle |
Design tokens
Section titled “Design tokens”Tokens this stylesheet reads (verified in CI). Override them in a theme or with the Theme Designer.
--aui-border-width | --aui-color-border | --aui-color-border-strong | --aui-color-disabled-bg | --aui-color-error-fg | --aui-color-focus-ring | --aui-color-on-primary | --aui-color-primary | --aui-color-surface | --aui-color-text | --aui-color-text-disabled | --aui-color-text-muted | --aui-duration-fast | --aui-easing-standard | --aui-focus-ring-offset | --aui-focus-ring-width | --aui-font-family-sans | --aui-font-size-md | --aui-font-size-sm | --aui-font-weight-medium | --aui-icon-size-md | --aui-icon-size-sm | --aui-line-height-normal | --aui-line-height-tight | --aui-radius-sm | --aui-space-1 | --aui-space-2 | --aui-space-4 | --aui-touch-target-min
TypeScript definitions
Section titled “TypeScript definitions”type CheckboxGroupOrientation = 'vertical' | 'horizontal';interface CheckboxGroupOption { value: string; label: string; description?: string; disabled?: boolean }interface CheckboxGroupIcons { checked: IconRef; error: IconRef }interface CheckboxGroupChangeDetail { value: string[]; validity: FieldValidity }Accessibility
Section titled “Accessibility”Pattern: Native <fieldset> + <legend> grouping native checkboxes, each with a <label for> (HTML; WAI-ARIA APG Checkbox).
Keyboard
Section titled “Keyboard”| Key | Context | Action |
|---|---|---|
| Tab / Shift+Tab | Any | Moves focus through each enabled checkbox in order. |
| Space | Checkbox focused | Toggles that option (native). |
| Element | Role |
|---|---|
| fieldset | group (native), named by the legend |
| input | checkbox (native) |
| check marks and icons | none (aria-hidden=true) |
ARIA attributes
Section titled “ARIA attributes”| Attribute | Element | Value |
|---|---|---|
aria-describedby |
fieldset | Group help text and visible error message ids |
aria-describedby |
input | That option’s help text id, when present |
aria-invalid |
input | “true” on every checkbox while the group error is shown (the group role does not support aria-invalid) |
Each native input is a tab stop and shows a color-focus-ring outline on :focus-visible.
WCAG 2.2 success criteria addressed
Section titled “WCAG 2.2 success criteria addressed”Automated test results: Accessibility and compliance.
Notes and known caveats
Section titled “Notes and known caveats”- The required asterisk is aria-hidden. Because checkboxes and the group role cannot carry aria-required, a visually hidden “(required)” (localizable message checkboxGroup.required) is part of the legend.
- Checked state is shown by a check mark, not only by the fill color.
- Errors appear after focus leaves the group by default, not when moving between options.
- Announcement of fieldset aria-describedby varies by screen reader; not yet manually verified with NVDA, JAWS, and VoiceOver.
Behavior
Section titled “Behavior”States
Section titled “States”default, hover, focus-visible, checked, disabled (group), disabled (option), required, invalid (message shown).
State transitions
Section titled “State transitions”| From | Trigger | To |
|---|---|---|
| any | user toggles an option | selection changed; aui-change; dirty |
| any | focus leaves the group | touched; messages shown (blur timing) |
| any | reportValidity() |
submitted; messages shown for every timing |
| invalid (custom error) | selection changes | custom error cleared |
| any | reset() |
initial selection; pristine, untouched |
Accessibility notes
Section titled “Accessibility notes”- The required asterisk is
aria-hidden. Checkboxes and the group role cannot carryaria-required, so a visually hidden “ (required)” (messagecheckboxGroup.required) is part of the legend. - Checked state is shown by a check mark, not only color.
- Errors appear after focus leaves the whole group, not when moving between options.
- Manual screen-reader verification is pending (see Known limitations).
Responsive behavior
Section titled “Responsive behavior”Vertical by default. orientation: 'horizontal' wraps options in a row. Labels and help text wrap; rows are at least touch-target-min tall.
Right-to-left
Section titled “Right-to-left”Logical properties and flex layout: boxes are at the inline start and horizontal options flow from the inline start.
Theming
Section titled “Theming”Colors come from role tokens only. In forced-colors mode boxes use Canvas/CanvasText, checked uses Highlight with a HighlightText mark, and disabled uses GrayText, with forced-color-adjust: none.
Global configuration
Section titled “Global configuration”configureAbsoluteUI({ components: { checkboxGroup: { validationTiming: 'input' } } });Changes apply to existing instances immediately.
Component configuration
Section titled “Component configuration”Instance options override global and theme defaults. All options are dynamic; changing options, name, or icons rebuilds the option rows.
icons.checked (default check) and icons.error (default alert-circle).
Security
Section titled “Security”All text uses textContent. Validation messages never include selected values. CSP-safe.
Data handling
Section titled “Data handling”No persistence, network access, or telemetry. With name, each checked native checkbox submits name=value.
Performance
Section titled “Performance”Two listeners per instance (delegated change, focusout), a shared document-level pointer tracker, and one configuration subscription. Rendering is linear in the number of options. Target: under 2 ms for 10 options; not yet covered by the performance test.
Supported data scale
Section titled “Supported data scale”Short lists, up to about 20 options. Unit-tested with 4 options.
Edge cases
Section titled “Edge cases”- An empty optional group is valid even with
minSelected(HTML constraint semantics); addrequiredto demand a selection. - Required and empty reports
value-missing(“Select an option.”), nottoo-few-selected. - Disabled options keep their checked state and are still reported in
valueandgetFormValue(); native form submission omits disabled inputs. update({ options })drops selections whose values no longer exist.
Errors
Section titled “Errors”| Code | Category | Cause |
|---|---|---|
CHECKBOX_GROUP_OPTIONS |
configuration | Missing label, empty or duplicate options, unknown value, invalid minSelected/maxSelected, minSelected > maxSelected, invalid orientation. |
Validation (validity.error) |
validation | value-missing, too-few-selected, too-many-selected, custom. |
A failed construction leaves no rendering, listeners, or subscriptions behind.
Known limitations
Section titled “Known limitations”- Selection-count messages have singular and plural forms only (
tooFewSelectedOne/tooFewSelected,tooManySelectedOne/tooManySelected); languages with more plural categories need a customvalidatemessage. - Some screen readers announce fieldset descriptions only when entering the group.
- Screen-reader behavior has not yet been manually verified with NVDA, JAWS, and VoiceOver.
Unsupported scenarios
Section titled “Unsupported scenarios”- HTML in labels or the legend.
- A mixed “select all” row inside the group (compose a Checkbox with the group).
- Nested groups.