Checkbox
Accessible checkbox with controlled + uncontrolled modes and an indeterminate state.
Checkbox is built on Radix and supports checked, unchecked, and indeterminate states
in both controlled and uncontrolled modes. Space toggles when focused; the box exposes
aria-checked="mixed" for the indeterminate state.
Installation
pnpm add @infinitibit_gmbh/ui @infinitibit_gmbh/theme-default
Usage
import '@infinitibit_gmbh/theme-default/theme.css';
import '@infinitibit_gmbh/ui/styles.css';
import { Checkbox } from '@infinitibit_gmbh/ui';
export function Example() {
return <Checkbox label="Accept terms" defaultChecked />;
}
States
Default, checked, indeterminate, error, and disabled. The error + indeterminate combination is intentionally not part of the design.
Controlled + indeterminate
Drive the checked prop with boolean | 'indeterminate' and update it from
onCheckedChange. Indeterminate is commonly used for a "select all" parent.
Group
CheckboxGroup lays out related checkboxes and exposes them as an accessible role="group"
(pass aria-label to name it). Two layouts: block (default) stacks them full-width;
inline wraps them in a content-width row. Selection state stays with your form — the group
is layout + grouping only.
import { Checkbox, CheckboxGroup } from '@infinitibit_gmbh/ui';
export function Example() {
return (
<CheckboxGroup aria-label="Notifications" layout="block">
<Checkbox label="Email" defaultChecked />
<Checkbox label="SMS" />
<Checkbox label="Push" />
</CheckboxGroup>
);
}
Rich checkbox
RichCheckbox is a bordered card with a title and an optional description — useful for
settings and selectable option lists. flipped moves the checkbox to the trailing edge.
The whole card is the click target. Compose several inside a CheckboxGroup.
import { RichCheckbox } from '@infinitibit_gmbh/ui';
export function Example() {
return (
<RichCheckbox
label="Email"
description="Account activity and security alerts."
defaultChecked
/>
);
}
API
RichCheckbox
| Prop | Type | Default | Description |
|---|---|---|---|
label | string | — | Card title (required) |
description | ReactNode | — | Optional secondary line |
flipped | boolean | false | Move the checkbox to the trailing edge |
Also accepts all Checkbox props (checked, defaultChecked, onCheckedChange, disabled, error, …).
CheckboxGroup
| Prop | Type | Default | Description |
|---|---|---|---|
layout | 'inline' | 'block' | 'block' | Vertical stack (block) or wrapping row |
children | ReactNode | — | The Checkbox items |
Renders role="group"; pass aria-label to name it. All other <div> props are forwarded.
Checkbox
| Prop | Type | Default | Description |
|---|---|---|---|
checked | boolean | 'indeterminate' | — | Controlled state; 'indeterminate' → aria-checked="mixed" |
defaultChecked | boolean | 'indeterminate' | false | Initial state (uncontrolled) |
onCheckedChange | (checked: boolean | 'indeterminate') => void | — | Called with the new state on toggle |
disabled | boolean | — | Prevents interaction |
error | boolean | — | Critical-ramp styling + aria-invalid |
label | ReactNode | — | Optional inline label, wired via htmlFor |
id | string | auto | Explicit id (falls back to useId) |
All other Radix Checkbox.Root props are forwarded.
Accessibility
- Renders with
role="checkbox"andaria-checkedof"true","false", or"mixed". - Space toggles via Radix; the focus ring uses
:focus-visible(keyboard only). errorsetsaria-invalid="true"so the invalid state is exposed to assistive tech.- An optional
labelis associated viahtmlFor, so clicking the label toggles the box. - Disabled checkboxes receive the
disabledattribute and are removed from the tab order.