import { Checkbox, CheckboxLabel } from "@hel/ui/checkbox"
export function CheckboxDemo() {When to use it#
A checkbox is for a yes or no that is saved later, with the rest of a form: accepting terms, opting in to emails, picking which columns to export. When someone can pick any number of options from a list, a group of checkboxes is the natural fit.
For a setting that takes effect the moment it flips, a switch reads better. For choosing exactly one option from a few, use radio buttons.
Import#
import { Checkbox, CheckboxLabel, CheckboxGroup } from "@hel/ui/checkbox"How it fits together#
Checkbox is only the box. The text next to it is a separate CheckboxLabel, and you put both inside a <label> that carries the group class:
<label className="group flex items-center gap-2">
<Checkbox />
<CheckboxLabel title="Remember me on this device" />
</label>Wrapping them in a real label makes the whole row clickable and names the box for screen readers, with no id or htmlFor to keep in step. The group class lets the label text notice when its checkbox is disabled and dim itself, so you only say disabled once.
Examples#
With a description#
CheckboxLabel takes a title and an optional description. Use items-start on the row so the box lines up with the first line when the description wraps.
import { Checkbox, CheckboxLabel } from "@hel/ui/checkbox"
export function CheckboxDescription() {Disabled#
Put disabled on the Checkbox. The title and description dim to match, since the label reads the state from the box. A disabled box keeps its ticked or unticked look, so people can still see the value they can't change.
import { Checkbox, CheckboxLabel } from "@hel/ui/checkbox"
import { Stack } from "@hel/ui/stack"
A group#
CheckboxGroup shares the ticked values between several boxes. Give each Checkbox a value, and start from defaultValue. Pass value and onValueChange instead when the rest of the form needs the list. Name the group with an aria-label or a heading, so a screen reader announces what the boxes are about.
import { Checkbox, CheckboxGroup, CheckboxLabel } from "@hel/ui/checkbox"
const CHANNELS = [Select all#
Add allValues to a controlled group and one Checkbox with the parent prop ticks or clears every child. When only some are ticked, the parent shows a dash, which is the indeterminate state.
import * as React from "react"
import { Checkbox, CheckboxGroup, CheckboxLabel } from "@hel/ui/checkbox"Controlled use#
A lone checkbox is uncontrolled by default, with defaultChecked for the starting state. For a controlled one, pass checked and onCheckedChange.
const [agreed, setAgreed] = React.useState(false)
<label className="group flex items-center gap-2">
<Checkbox checked={agreed} onCheckedChange={setAgreed} />
<CheckboxLabel title="I accept the terms" />
</label>Keyboard#
| Key | Action |
|---|---|
Tab | Moves to the next checkbox. |
Space | Ticks or unticks the focused checkbox. |
Props#
Checkbox#
| Prop | Type | Default |
|---|---|---|
checked | boolean | none |
defaultChecked | boolean | false |
onCheckedChange | (checked: boolean) => void | none |
indeterminate | boolean | false |
value | string, the value in a group | none |
parent | boolean, makes it the select all box of a group | false |
disabled | boolean | false |
required | boolean | false |
name | string, for form submission | none |
Checkbox also takes every prop of the Base UI checkbox.
CheckboxLabel#
| Prop | Type | Default |
|---|---|---|
title | ReactNode | required |
description | ReactNode | none |
CheckboxGroup#
| Prop | Type | Default |
|---|---|---|
value | string[] | none |
defaultValue | string[] | none |
onValueChange | (value: string[]) => void | none |
allValues | string[], needed for a parent checkbox | none |
disabled | boolean | false |