Skip to the content
BooleanPress UI

Form

Checkbox

Lets people choose one or more options, or shows that a group is partly chosen.

Import

import { Checkbox } from "@booleanpress/ui/checkbox"

Usage

Give every checkbox a visible name: a Label whose htmlFor is the checkbox's id. Clicking the label toggles it.

import { Checkbox } from "@booleanpress/ui/checkbox"
import { Label } from "@booleanpress/ui/label"

export function Terms() {
  return (
    <div className="flex items-center gap-2">
      <Checkbox id="terms" />
      <Label htmlFor="terms">Accept the terms</Label>
    </div>
  )
}

It is uncontrolled with defaultChecked, or controlled with checked and onCheckedChange. checked is true, false or "indeterminate"; onCheckedChange receives the same three values. It also takes a button's attributes, such as disabled, and, inside a form, name and value.

Examples

Basic

Unchecked and checked, each named by its label.

Indeterminate

A box that chooses a whole group shows a dash while only some of the group is chosen.

Disabled

A disabled box keeps its state, ignores clicks and Space, and leaves the tab order.

Invalid

aria-invalid draws the error border; aria-describedby reads the error message with the name.

Accessibility

Semantics
A button with role="checkbox" and aria-checked (true, false or mixed). Inside a form, it also renders a hidden native input, so the value is submitted with the form.
Labels
Name every checkbox: a Label with htmlFor, or aria-label when no visible text fits. Put an error message in aria-describedby.
Focus
It is in the tab order. The focus ring shows on keyboard focus, not on click.
Known limits
  • The box is 16 px. Keep its label beside it, so the label adds to the target and the pair meets WCAG 2.5.8's 24 px.

Keyboard

Keyboard
KeyBehaviour
SpaceToggles between checked and unchecked. From the indeterminate state, it becomes checked.

API

Checkbox

Renders Radix Checkbox.Root and passes it every other prop.

Checkbox props
PropTypeDefaultDescription
asChildbooleanRender the child element instead, with this part's behaviour and classes merged onto it.
checkedboolean | "indeterminate"The state, when you control it. Pair it with onCheckedChange.
defaultCheckedboolean | "indeterminate"The state it starts in, when it controls itself.
onCheckedChange((checked: boolean | "indeterminate") => void)Called with the new state when it is toggled.
requiredbooleanThe form cannot be submitted until it is checked.

Every part takes className, merged with its defaults by cn(), and ref, which reaches the element it renders.

Data attributes: data-slot="checkbox" (Checkbox).

Theming

The unchecked edge is --control, at least 3:1 against the surface (WCAG 1.4.11); checked and mixed fill with --primary and --primary-foreground; focus is --ring at 50 %; invalid is --destructive.

The tokens its classes read. Change their values in your theme, and it follows.

Theme tokens
TokenUsed for
--controlborder
--destructiveborder, focus ring
--inputborder, background
--primaryborder, background
--primary-foregroundtext
--ringborder, focus ring