Skip to content

Checkbox

Form InputsSince 0.2.0
import { Checkbox } from '@absoluteui/components/checkbox';
import '@absoluteui/components/checkbox/style.css';

Using Angular? See Checkbox for Angular.

A single on/off choice submitted with a form. Checkbox renders a native <input type="checkbox"> restyled with appearance: none, so the native input stays the focus target, the hit target, and the source of truth for checked and mixed state. It adds a label, required indicator, help text, and a localized validation message. The check and minus marks are icons layered over the box.

  • A single independent yes/no choice that is submitted with a form, such as accepting terms or opting into a newsletter.
  • A “select all” parent that shows a mixed state when only some children are selected.
  • A choice that must be confirmed before continuing (required).
  • Several related choices: use Checkbox Group.
  • One choice from a set of mutually exclusive options: use Radio Group.
  • A setting that takes effect immediately: use Switch.
import { Checkbox } from '@absoluteui/components/checkbox';
const host = document.createElement('div');
document.body.append(host);
const terms = Checkbox.create(host, { label: 'I accept the terms and conditions', name: 'terms', value: 'accepted', required: true });
host.addEventListener('aui-change', () => {
host.dataset.valid = String(terms.validity.valid);
});
import { Checkbox } from '@absoluteui/components/checkbox';
const host = document.createElement('div');
document.body.append(host);
const all = Checkbox.create(host, { label: 'Select all files', indeterminate: true });
function syncSelectAll(selected: number, total: number): void {
all.setChecked(selected === total, selected > 0 && selected < total);
}
syncSelectAll(3, 5);
import { configureAbsoluteUI } from '@absoluteui/core';
configureAbsoluteUI({ components: { checkbox: { validationTiming: 'input' } } });
import { Checkbox } from '@absoluteui/components/checkbox';
import '@absoluteui/components/checkbox/style.css';
const host = document.querySelector<HTMLElement>('#newsletter');
if (host) {
const newsletter = Checkbox.create(host, { label: 'Send me the monthly newsletter', name: 'newsletter', value: 'monthly' });
host.addEventListener('aui-change', () => {
host.dataset.subscribed = String(newsletter.checked);
});
}
import { Checkbox } from '@absoluteui/components/checkbox';
const host = document.createElement('div');
document.body.append(host);
Checkbox.create(host, { label: 'I accept the terms and conditions', name: 'terms', value: 'accepted', required: true });
<div class="aui-field aui-checkbox" data-aui-control> (consumer host)
<div class="aui-checkbox__row">
<span class="aui-checkbox__box">
<input type="checkbox" class="aui-checkbox__input">
<span class="aui-checkbox__mark aui-checkbox__mark--checked"><svg aria-hidden="true"></span>
<span class="aui-checkbox__mark aui-checkbox__mark--indeterminate"><svg aria-hidden="true"></span>
</span>
<label class="aui-field__label aui-checkbox__label" for=input>Label<span class="aui-field__required" aria-hidden="true">*</span></label>
</div>
<div class="aui-field__description"> (optional)
<div class="aui-field__error aui-validation-message"> (when shown)
</div>
Checkbox.create(host: HTMLElement, options: CheckboxOptions): Checkbox

Global configuration key: checkbox (see Configuration).

Option Type Default Description
label string Visible label and accessible name; clicking it toggles the checkbox. Required.
hideLabel boolean false Visually hide the label; it remains the accessible name.
checked boolean false Initial checked state; also restored by reset().
indeterminate boolean false Mixed state (aria-checked=mixed via the native property). Cleared when the user toggles.
value string "on" Submitted value when checked.
name string Form field name.
description string Help text referenced by aria-describedby.
required boolean false The box must be checked; shows the required indicator.
disabled boolean false Disables the checkbox.
validate (checked: boolean) => string | null Consumer validation; return a message to mark the state invalid.
icons Partial<{ checked: IconRef; indeterminate: 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 locale. Globally configurable. Inherited from common configuration.
Property Type Description
host HTMLElement Consumer host; its children are owned by the component.
input HTMLInputElement The native checkbox.
checked boolean Current checked state.
indeterminate boolean Current mixed state.
value string Submitted value when checked.
name string | null Form field name.
label string Label text.
disabled boolean Disabled state.
validity FieldValidity { valid, error, message }; computed on every change.
dirty boolean Checked or mixed state differs from the initial state.
touched boolean Focus has left the control at least once.
options Readonly<CheckboxOptions> Current instance options.
Method Description
setChecked(checked: boolean, indeterminate?: boolean): void Programmatic state (no events); clears the mixed state unless given and clears an external custom error.
update(options: Partial<CheckboxOptions>): void Merge and apply options.
reportValidity(): boolean Show messages now and return validity.
setCustomError(message: string | null): void External error; cleared when the user toggles.
getFormValue(): string | null value when checked, otherwise null.
focus(): void Focus the checkbox.
reset(): void Restore the initial checked and mixed state and clear dirty/touched/submitted state.
destroy(): void Remove rendering, listeners, registration, and subscriptions.
Event Detail Bubbles Cancelable Description
aui-change { checked: boolean; value: string; validity: FieldValidity } Yes No The user toggled the checkbox.

All rules live in the aui.components cascade layer, so application styles override them without specificity battles.

Class Purpose
aui-field aui-checkbox Host.
aui-checkbox--invalid | --disabled State modifiers on the host.
aui-field__label | __required | __description | __error Shared field chrome.
aui-checkbox__row Box and label row.
aui-checkbox__box Positioning wrapper for the input and marks.
aui-checkbox__input Native checkbox, restyled as the box.
aui-checkbox__mark | __mark--checked | __mark--indeterminate Decorative check and minus marks.
aui-checkbox__label The label (also aui-field__label).
Slot Default icon
checked check
indeterminate minus
error alert-circle

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-font-weight-regular | --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-touch-target-min

type ValidationTiming = 'blur' | 'input' | 'submit';
interface FieldValidity { readonly valid: boolean; readonly error: ValidationErrorCode | null; readonly message: string }
interface CheckboxIcons { checked: IconRef; indeterminate: IconRef; error: IconRef }
interface CheckboxChangeDetail { checked: boolean; value: string; validity: FieldValidity }

Pattern: Native <input type=“checkbox”> with a <label for> association (HTML; WAI-ARIA APG Checkbox, dual- and tri-state).

Key Context Action
Tab / Shift+Tab Any Moves focus to and from the checkbox.
Space Checkbox focused Toggles the checkbox (native). A mixed checkbox becomes checked.
Element Role
input checkbox (native); aria-checked=mixed via the indeterminate property
marks and icons none (aria-hidden=true)
Attribute Element Value
aria-describedby input Help text and visible error message ids
aria-invalid input “true” only while an error message is shown

The native input is the focus target and shows a color-focus-ring outline on :focus-visible, offset from the box.

Criterion Level Note
1.3.1 Info and Relationships A
1.4.1 Use of Color A
1.4.3 Contrast (Minimum) AA
1.4.11 Non-text Contrast AA
2.1.1 Keyboard A
2.4.7 Focus Visible AA
2.5.3 Label in Name A
2.5.8 Target Size (Minimum) AA
3.3.1 Error Identification A
3.3.2 Labels or Instructions A
4.1.2 Name, Role, Value A

Automated test results: Accessibility and compliance.

  • The required asterisk is aria-hidden; required state is conveyed by the native required attribute.
  • Checked and mixed states are shown by a check or minus shape, not only by the fill color.
  • Clicking the label toggles the checkbox, extending the hit target.
  • Errors appear after the first blur by default; when focus leaves because of a pointer press, the message appears after the pointer is released so the click is not displaced.
  • Screen-reader announcement of the mixed state and error message has not yet been manually verified with NVDA, JAWS, and VoiceOver.

default, hover, focus-visible, checked, indeterminate (mixed), disabled, disabled checked, required, invalid (message shown).

From Trigger To
unchecked click, label click, or Space checked; aui-change
checked click, label click, or Space unchecked; aui-change
indeterminate user toggle checked (native), mixed cleared
any focus leaves the host touched; messages shown (blur timing)
any reportValidity() submitted; messages shown for every timing
invalid (custom error) user toggles custom error cleared
any reset() initial state; pristine, untouched
  • The required asterisk is aria-hidden; the native required attribute conveys the state.
  • Checked and mixed states use a check or minus shape, not only color (WCAG 1.4.1).
  • The label is clickable, so the target is the whole row (WCAG 2.5.8); the row is at least touch-target-min tall.
  • Errors appear after the first blur by default. When focus leaves because of a pointer press, the message appears after the pointer is released so the pending click is not displaced.
  • Manual screen-reader verification is pending (see Known limitations).

The box is fixed-size; the label wraps beside it. Help text and messages align with the label.

Logical properties throughout: the box is at the inline start and help text is indented from the inline start. The check mark is not mirrored.

Colors come from role tokens only. High-contrast themes widen border-width. In forced-colors mode the box uses Canvas/CanvasText, checked uses Highlight with a HighlightText mark, and disabled uses GrayText, with forced-color-adjust: none so the custom box stays visible.

configureAbsoluteUI({ components: { checkbox: { validationTiming: 'input' } } });

Changes apply to existing instances immediately.

Instance options override global and theme defaults. All options are dynamic.

icons.checked (default check), icons.indeterminate (default minus), and icons.error (default alert-circle).

All text uses textContent. Validation messages never include the value. CSP-safe: no inline styles or HTML strings.

No persistence, network access, or telemetry. The native input submits name=value when checked and name is set.

Two listeners per instance (change, focusout), one document-level pointer tracker shared by all fields, and one configuration subscription. Target: under 1 ms per Checkbox.create; not yet covered by the performance test.

One value per instance. Not yet included in the 1,000-instance performance test.

  • Toggling a mixed checkbox makes it checked and clears the mixed state (native behavior).
  • setChecked(true) clears the mixed state; setChecked(false, true) shows mixed.
  • A mixed checkbox that is not checked submits nothing.
Code Category Cause
CHECKBOX_OPTIONS configuration Missing label, non-string value, or non-function validate.
Validation (validity.error) validation value-missing (“Check this box to continue.”), custom.

A failed construction leaves no rendering, listeners, or subscriptions behind.

  • The mixed state is presentational and never submitted.
  • The box alone is 1.25rem; the 24px target is met by the row and label.
  • Screen-reader behavior of the mixed state and messages has not yet been manually verified with NVDA, JAWS, and VoiceOver.
  • HTML (for example links) inside the label.
  • Read-only checkboxes.