Checkbox
A form control that lets users select one or more options. Supports checked, unchecked, and indeterminate states. Five sizes, five intents, label/description/error patterns, and a CheckboxGroup compound component with select-all support.
Installation
pnpm add @tessinaui/uiUsage
import { Checkbox, CheckboxGroup } from "@tessinaui/ui";{/* Standalone */}
<Checkbox label="Accept terms and conditions" />
{/* Controlled */}
<Checkbox
checked={accepted}
onCheckedChange={(val) => setAccepted(val as boolean)}
label="Accept terms"
/>
{/* With description and error */}
<Checkbox
label="Accept terms"
required
intent="error"
errorMessage="You must accept the terms to continue."
/>
{/* Group with select-all */}
<CheckboxGroup
value={selected}
onValueChange={setSelected}
allValues={["a", "b", "c"]}
label="Choose options"
>
<Checkbox name="a" value="a" label="Option A" />
<Checkbox name="b" value="b" label="Option B" />
<Checkbox name="c" value="c" label="Option C" />
</CheckboxGroup>Playground
Contact List Example
A common pattern combining Checkbox with Avatar for selecting contacts or friends.
Showcase
API Reference
Checkbox props
| Prop | Type | Default | Description |
|---|---|---|---|
variant | "filled" | "outline" | "filled" | Unchecked style: filled has bg-secondary, outline is transparent |
size | "xs" | "sm" | "md" | "lg" | "xl" | "md" | Visual size of the checkbox box |
intent | "none" | "error" | "warning" | "success" | "info" | "none" | Semantic color for border / fill |
checked | boolean | — | Controlled checked state |
defaultChecked | boolean | false | Uncontrolled initial state |
onCheckedChange | (checked: boolean) => void | — | Change handler |
indeterminate | boolean | false | Mixed state (renders Minus icon) |
disabled | boolean | false | Prevents interaction |
readOnly | boolean | false | Prevents interaction, accessible |
required | boolean | false | HTML required + asterisk on label |
label | string | — | Text label rendered beside the checkbox |
description | string | — | Helper text below the label |
errorMessage | string | — | Error text (overrides description, adds AlertCircle) |
labelPosition | "left" | "right" | "right" | Which side the label appears on |
dir | "ltr" | "rtl" | — | Text direction for the wrapper |
name | string | — | Input name for form submission |
value | string | — | Value submitted with the form |
parent | boolean | — | Marks as select-all within a CheckboxGroup |
className | string | — | Extra classes on the wrapper <div> |
All other native attributes are forwarded to the underlying <span> (Base UI).
CheckboxGroup props
| Prop | Type | Default | Description |
|---|---|---|---|
value | string[] | — | Controlled list of checked values |
defaultValue | string[] | [] | Uncontrolled initial values |
onValueChange | (value: string[]) => void | — | Change handler |
allValues | string[] | — | All possible values — enables select-all indeterminate logic |
disabled | boolean | false | Disables all checkboxes in the group |
orientation | "vertical" | "horizontal" | "vertical" | Stack direction |
variant | "filled" | "outline" | "filled" | Propagated to child Checkboxes |
size | CheckboxSize | "md" | Propagated to child Checkboxes |
intent | CheckboxIntent | "none" | Propagated to child Checkboxes |
label | string | — | Group legend |
description | string | — | Helper text below legend |
errorMessage | string | — | Error text for the group |
required | boolean | false | Asterisk on group legend |
dir | "ltr" | "rtl" | — | Text direction for the group wrapper |
States
| State | Visual |
|---|---|
| Unchecked | Empty box with border |
| Checked | Filled box + Check icon (white) |
| Indeterminate | Filled box + Minus icon (white) |
| Disabled unchecked | Muted empty box |
| Disabled checked | Muted filled box + muted icon |
| Focus | Ring outline (2px) |
| Hover (unchecked) | Darker border |
| Hover (checked) | Slightly darker fill |
Sizes
| Size | Box | Rounded | Text size |
|---|---|---|---|
xs | 14×14 px | rounded-sm | text-xs |
sm | 16×16 px | rounded | text-sm |
md | 20×20 px | rounded-md | text-sm |
lg | 24×24 px | rounded-md | text-base |
xl | 28×28 px | rounded-lg | text-base |
Intents
| Intent | Unchecked border | Checked fill |
|---|---|---|
none | border-border | bg-primary |
error | border-error | bg-error |
warning | border-warning | bg-warning |
success | border-success | bg-success |
info | border-info | bg-info |
Checkbox Group patterns
Uncontrolled
<CheckboxGroup defaultValue={["email"]} label="Notifications">
<Checkbox name="email" value="email" label="Email" />
<Checkbox name="sms" value="sms" label="SMS" />
<Checkbox name="push" value="push" label="Push" />
</CheckboxGroup>Select all (parent)
const all = ["a", "b", "c"];
const [selected, setSelected] = useState<string[]>([]);
<CheckboxGroup value={selected} onValueChange={setSelected} allValues={all}>
<Checkbox
name="all"
parent
label="Select all"
checked={selected.length === all.length}
indeterminate={selected.length > 0 && selected.length < all.length}
onCheckedChange={(checked) => setSelected(checked ? [...all] : [])}
/>
{all.map((v) => (
<Checkbox key={v} name={v} value={v} label={v} />
))}
</CheckboxGroup>Horizontal
<CheckboxGroup orientation="horizontal" label="Days">
<Checkbox value="mon" label="Mon" />
<Checkbox value="tue" label="Tue" />
<Checkbox value="wed" label="Wed" />
</CheckboxGroup>Accessibility
- Hidden
<input type="checkbox">rendered by Base UI — native form semantics aria-checked="mixed"set automatically for indeterminate statearia-invalidset on checkbox + group whenerrorMessageis presentaria-describedbylinks error messages to their respective controls- Required:
aria-required+ nativerequiredattribute on hidden input - Focus ring visible at all sizes — complies with WCAG 2.1 AA (3:1 contrast)
- Touch target: minimum 44×44 px achieved via padding on the wrapper
- Group rendered as
<fieldset>+<legend>for screen reader context
Field
A text input field with a label, helper text, FieldDropdown prefix, Button suffix, leading/trailing icon buttons, a clearable button, and a character counter. Supports all intent states and full RTL layout.
Radio
A form control that lets users select exactly one option from a group. Five sizes, five intents, label/description/error patterns, RadioGroup compound component, and RadioCard full-surface variant.