Checkbox
Selects independent options and communicates partial selection when needed.
Design
Functional preview
Running with stable DS HTML and CSS, without a component JavaScript runtime.
Loading functional preview…
Open the HTML/CSS/JS playground
Anatomy
1
2
3
4
1 Label (
2 Input (
3 Checkmark — CSS pseudo-element, visible when checked.
4 Indeterminate dash — CSS pseudo-element, visible when
.ds-checkbox-label) — wraps checkbox + text, extends click target.2 Input (
.ds-checkbox) — styled native <input type="checkbox">.3 Checkmark — CSS pseudo-element, visible when checked.
4 Indeterminate dash — CSS pseudo-element, visible when
indeterminate = true.
Default
Indeterminate
Sizes
Error Group
Disabled
States
| State | CSS trigger | Visual change | Token |
|---|---|---|---|
| Unchecked | --- | Neutral box fill and border | component.checkbox.box.fill.unchecked.default, component.checkbox.box.border-color.unchecked.default |
| Unchecked hover | :hover | Darker neutral box border/fill | component.checkbox.box.fill.unchecked.hover, component.checkbox.box.border-color.unchecked.hover |
| Checked | :checked | Primary box fill with checkmark | component.checkbox.box.fill.checked.default, component.checkbox.mark.fill.checked.default |
| Checked hover | :checked:hover | Darker primary box fill | component.checkbox.box.fill.checked.hover, component.checkbox.mark.fill.checked.hover |
| Indeterminate | :indeterminate | Primary box fill with indeterminate mark | component.checkbox.box.fill.indeterminate.default, component.checkbox.mark.fill.indeterminate.default |
| Focus | :focus-visible | 2px outline ring | component.checkbox.focus-ring.radius.default + component.focus-ring.* |
| Error group | .ds-checkbox-group--error | Error border on controls and message below group | component.checkbox.box.border-color.unchecked.error, semantic.feedback.error.content-default |
| Disabled | [disabled] | Muted box, mark and label | component.checkbox.box.fill.*.disabled, semantic.content.disabled |
Figma properties
| Property | Type | Default | Description |
|---|---|---|---|
Show Label | Boolean | true | Shows or hides the control label |
Label | Text | "Rótulo" | Label text (label/md) |
Show Description | Boolean | false | Shows descriptive text below the label |
Description | Text | "Texto descritivo" | Multiline description text (body/sm) |
Show Helper Text | Boolean | false | Shows helper text below the description |
Helper Text | Text | "Texto auxiliar" | Caption/sm annotation (content/secondary) |
Usage
When to use
- Zero, one, or multiple independent options may be selected.
- A binary option has a visible label and will be confirmed in a form.
When not to use
- Only one option in a group may be selected; use Radio.
- The change immediately turns a setting on or off; use Toggle.
Implementation
- Status
- Stable
- Distribution
- npm package
Installation
npm install ds-tispnpm add ds-tisyarn add ds-tisbun add ds-tisImports
import 'ds-tis/css'Markup
<label class="ds-checkbox-label">
<input class="ds-checkbox" type="checkbox" name="notifications" value="enabled" />
<span class="ds-checkbox__content">
<span class="ds-checkbox__label">Receber novidades</span>
</span>
</label>Web implementation contract
Token mapping
| Property | Token Component | CSS variable |
|---|---|---|
| box size (sm/md/lg) | component.checkbox.box.size.* | --ds-checkbox-box-size-* |
| box fill | component.checkbox.box.fill.*.* | --ds-checkbox-box-fill-* |
| box border | component.checkbox.box.border-color.*.* | --ds-checkbox-box-border-color-* |
| mark fill | component.checkbox.mark.fill.*.* | --ds-checkbox-mark-fill-* |
| target height | component.checkbox.target.height.* | --ds-checkbox-target-height-* |
| focus ring | component.checkbox.focus-ring.radius.default + component.focus-ring.* | --ds-focus-ring-* + --ds-checkbox-focus-ring-radius-default |
| label/helper/description/error | component.form-field.* | --ds-form-field-* |
CSS classes
| Class | Description |
|---|---|
ds-checkbox | Custom styled native checkbox |
ds-checkbox-label | Label wrapper (wraps checkbox + text) |
ds-checkbox--sm | Small size (16px) |
ds-checkbox--lg | Large size (24px) |
ds-checkbox-group--error | Error state for a group of checkboxes |
ds-checkbox-group__error | Error message text for the group |
ds-checkbox__content | Vertical frame stacking label, description, and helper text |
ds-checkbox__label | Label text inside content frame (label/md) |
ds-checkbox__description | Multiline description text (body/sm, content/default) |
ds-checkbox__helper | Helper annotation (caption/sm, content/secondary) |
Accessibility
Keyboard interaction
| Key | Action |
|---|---|
Tab | Moves focus to the next checkbox |
Space | Toggles the checked state |
Accessibility
| WCAG criterion | Requirement | Status |
|---|---|---|
| 1.3.1 Info and Relationships (A) | Group related checkboxes in <fieldset> + <legend> | ✓ |
| 2.4.11 Focus Appearance (AA) | Focus ring visible via :focus-visible | ✓ |
| 2.5.8 Target Size min (AA) | Label extends click target beyond the checkbox itself | ✓ |
| 4.1.2 Name, Role, Value (A) | Native <input type="checkbox"> provides role + state automatically | ✓ |
| 3.3.1 Error Identification (A) | Group error communicated via ds-checkbox-group--error | ✓ |
Implementation notes
Uses native <input type="checkbox"> for built-in keyboard and screen reader support. The indeterminate state must be set via JavaScript (el.indeterminate = true). Always wrap related checkboxes in a <fieldset> with a <legend> to provide group context to assistive technology.
Invisible label — requires explicit ARIA
When Show Label = false and Show Description = true, link the <input> to the description via aria-labelledby="description-id". If neither is visible, use aria-label directly on the <input>. Helper Text should always be linked via aria-describedby="helper-id".
Output responsibility
Preserve native element semantics, accessible names, keyboard behavior, and visible focus.
Validation evidence
Covered by the stable Storybook, public runtime tests when applicable, keyboard scenarios, responsive checks, and Axe.