Skip to content

Checkbox

Edit on GitHub

Checkboxes let users toggle a binary choice or select multiple options from a list.

@volvo-cars/css v2.5.1@volvo-cars/react-forms v2.0.1

Use Checkbox from @volvo-cars/react-forms, or use a native checkbox styled by @volvo-cars/css.

Show codeHide code
import { Checkbox } from '@volvo-cars/react-forms';
export function CheckboxBasic() {
return (
<Checkbox name="updates" label="Send me product updates" defaultChecked />
);
}

The hint prop adds a description below the label, linked via aria-describedby. Use hints for supplementary context. Place links here rather than in the label text.

Pass defaultChecked to pre-select a checkbox without managing state.

Pass checked and onChange when you need to read or drive the state externally.

Set errorMessage to display an inline error and mark the checkbox invalid. The error is hidden when the checkbox is disabled. You can also force invalid styling with aria-invalid.

The indeterminate prop shows a visual “partially selected” state. Useful for parent/child checkbox hierarchies. It is visual-only and does not affect the submitted value; you manage the checked state of each child yourself.

@volvo-cars/css styles native <input type="checkbox"> elements automatically. No class needed. If you add any class to the input, include the checkbox class to keep design system styles.

Show codeHide code
<div class="flex flex-col gap-16">
<div class="flex-row">
<input type="checkbox" name="updates" id="updates" value="updates" />
<label class="ml-8" for="updates">Send me product updates</label>
</div>
<div class="flex-row">
<input type="checkbox" name="terms" id="terms" value="terms" checked />
<label class="ml-8" for="terms">I agree to the terms</label>
</div>
<div class="flex-row">
<input type="checkbox" name="offers" id="offers" value="offers" disabled />
<label class="ml-8" for="offers">Get special offers</label>
</div>
</div>

Wrap the label and hint in a flex-col stack-4 container. Use micro text-secondary for hint text. Place links in the hint, not in the label.

Set aria-invalid="true" on the input and link an error message with aria-describedby.

Key responsibilities from the WCAG audit:

  • Label every checkbox: Checkbox requires a label prop. For CSS-only, pair each <input> with a <label for>.
  • Keep labels plain text: add any required links in the hint instead.
  • Error association: use errorMessage (React) or aria-invalid + aria-describedby (CSS-only) to communicate errors.
  • Pointer target size: the checkbox control is smaller than 44×44 px, but the adjacent label extends the clickable area.
  • Status messages: VoiceOver in Safari has known issues announcing error messages on checkboxes (WCAG 4.1.3). Test with multiple screen readers.

The default keyboard focus indicator wraps the checkbox container, including its visible label.

Checkbox with keyboard focus

Checkbox and label with keyboard focus.

PropTypeRequiredDefault
namestring-
The name of the input to use when submitting the form.
labelstring-
Concise label for the checkbox. Labels should not contain HTML, add any required links in the `hint` instead.
valuestring-on
The value of the checkbox that will be submitted with the form data. @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox#value
requiredboolean--
Makes the checkbox required.
errorMessagestring--
Set the error message of a checkbox and mark it invalid.
aria-invalidboolean-false
Force the checkbox to be invalid.
checkedboolean--
Whether the checkbox is checked. Makes the input controlled.
onChangeChangeEventHandler<HTMLInputElement, Element>--
Fires when the input is checked or unchecked.
defaultCheckedboolean--
Whether an (uncontrolled) checkbox is checked by default.
indeterminateboolean-false
Indicates if the checkbox is in an indeterminate state, often used to show a "partially selected" state (e.g., when some child checkboxes are selected). This state is visual-only and does not affect the checkbox's submitted value.
hiddenboolean--
idstring--
titlestring--
dirstring--
langstring--
slotstring--
translate"yes" | "no"--
classNamestring--
styleCSSProperties--
tabIndexnumber--
onPointerDownPointerEventHandler<Element>--
onPointerEnterPointerEventHandler<Element>--
onPointerLeavePointerEventHandler<Element>--
onPointerMovePointerEventHandler<Element>--
onPointerUpPointerEventHandler<Element>--
disabledboolean-false
Disables the input. Use sparingly as it can be non-obvious to users why an input has been disabled. Prefer showing validation messages and hints instead.
autoFocusboolean-false
Gives the input focus on page load. Use sparingly as it can be confusing to screen-reader and mobile users.
readOnlyboolean-false
Makes the input read-only. Use sparingly, it's often preferred to present the data as regular text or in a table instead.
formstring--
Id of a form element that this input should be associated with. Defaults to the containing form element.
hintReactNode--
Additional hint or description.
enterKeyHint"done" | "go" | "next" | "previous" | "search" ...--
Hint the browser about what label to show for the Enter button on mobile keyboards.
aria-describedbystring--
aria-labelledbystring--
onInvalidFormEventHandler<HTMLInputElement>--
Fires if the input fails validation on form submit.
onFocusFocusEventHandler<HTMLInputElement>--
onBlurFocusEventHandler<HTMLInputElement>--
onKeyDownKeyboardEventHandler<HTMLInputElement>--
onKeyUpKeyboardEventHandler<HTMLInputElement>--