InfinitiBit Design System

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

PropTypeDefaultDescription
labelstringCard title (required)
descriptionReactNodeOptional secondary line
flippedbooleanfalseMove the checkbox to the trailing edge

Also accepts all Checkbox props (checked, defaultChecked, onCheckedChange, disabled, error, …).

CheckboxGroup

PropTypeDefaultDescription
layout'inline' | 'block''block'Vertical stack (block) or wrapping row
childrenReactNodeThe Checkbox items

Renders role="group"; pass aria-label to name it. All other <div> props are forwarded.

Checkbox

PropTypeDefaultDescription
checkedboolean | 'indeterminate'Controlled state; 'indeterminate'aria-checked="mixed"
defaultCheckedboolean | 'indeterminate'falseInitial state (uncontrolled)
onCheckedChange(checked: boolean | 'indeterminate') => voidCalled with the new state on toggle
disabledbooleanPrevents interaction
errorbooleanCritical-ramp styling + aria-invalid
labelReactNodeOptional inline label, wired via htmlFor
idstringautoExplicit id (falls back to useId)

All other Radix Checkbox.Root props are forwarded.

Accessibility

  • Renders with role="checkbox" and aria-checked of "true", "false", or "mixed".
  • Space toggles via Radix; the focus ring uses :focus-visible (keyboard only).
  • error sets aria-invalid="true" so the invalid state is exposed to assistive tech.
  • An optional label is associated via htmlFor, so clicking the label toggles the box.
  • Disabled checkboxes receive the disabled attribute and are removed from the tab order.

On this page