Skip to content

Checkbox

Edit on GitHub

An input for choosing from predefined options, either as a standalone toggle or as part of a group where users can select multiple values from a list.

@volvo-cars/css v3.1.0@volvo-cars/react-forms v3.1.0

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 />
);
}

@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>

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. For CSS-only usage, set aria-invalid="true" on the input and link an error message with aria-describedby.

Set disabled on the checkbox to prevent interaction. The adjacent label stays visible but no longer receives pointer or keyboard focus.

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.

The hint prop adds a description below the label, linked via aria-describedby. Use hints for supplementary context, and keep the label as a complete plain-text description of the choice. Place links in the hint. See Rich hints for the shared React API and Markdown support. For CSS-only usage, wrap the label and hint in a flex-col stack-4 container and use micro text-secondary for the hint text.

Group checkboxes in a vertical list with 16px between each item. Vertical stacking is the preferred orientation and scans best for longer lists. A horizontal layout works for a short set, such as two or three options.

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 keyboard focus indicator outlines the checkbox control itself, not the label.

Checkbox 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. Supports text, links and block content such as paragraphs or Markdown output.
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>--