Thrive Design System

Components

Checkbox

A control that allows users to select one or more options from a set, with support for indeterminate states

Installation

npm install @thrivecart/ui
yarn add @thrivecart/ui
pnpm add @thrivecart/ui
bun add @thrivecart/ui

Usage

Import the Checkbox component from the package:

import { Checkbox, Label } from '@thrivecart/ui';

Examples

Basic Checkbox

Simple Checkbox

Basic checkbox with label

<div className="flex items-center space-x-2">
<Checkbox id="terms" />
<Label htmlFor="terms" className='font-normal'>Accept terms and conditions</Label>
</div>

Checked State

Controlled Checkbox

Checkbox with controlled state

function ControlledCheckbox() {
const [checked, setChecked] = React.useState(true);

return (
  <div className="flex items-center space-x-2">
    <Checkbox
      id="controlled"
      checked={checked}
      onCheckedChange={setChecked}
    />
    <Label htmlFor="controlled" className='font-normal'>
      Receive email notifications
    </Label>
  </div>
);
}

Checkbox Group

Multiple Checkboxes

Group of related checkboxes

function CheckboxGroup() {
const [selected, setSelected] = React.useState(['email']);

const toggleOption = (option) => {
  setSelected(prev =>
    prev.includes(option)
      ? prev.filter(o => o !== option)
      : [...prev, option]
  );
};

return (
  <div className="space-y-3">
    <Label className="text-base font-medium">Notification Preferences</Label>
    <div className="space-y-2">
      <div className="flex items-center space-x-2">
        <Checkbox
          id="email"
          checked={selected.includes('email')}
          onCheckedChange={() => toggleOption('email')}
        />
        <Label htmlFor="email" className='font-normal'>Email notifications</Label>
      </div>
      <div className="flex items-center space-x-2">
        <Checkbox
          id="sms"
          checked={selected.includes('sms')}
          onCheckedChange={() => toggleOption('sms')}
        />
        <Label htmlFor="sms" className='font-normal'>SMS notifications</Label>
      </div>
      <div className="flex items-center space-x-2">
        <Checkbox
          id="push"
          checked={selected.includes('push')}
          onCheckedChange={() => toggleOption('push')}
        />
        <Label htmlFor="push" className='font-normal'>Push notifications</Label>
      </div>
    </div>
  </div>
);
}

Indeterminate State

Parent/Child Selection

Checkbox with indeterminate state for partial selection

function IndeterminateExample() {
const [items, setItems] = React.useState([
  { id: '1', label: 'Item 1', checked: true },
  { id: '2', label: 'Item 2', checked: false },
  { id: '3', label: 'Item 3', checked: true },
]);

const allChecked = items.every(item => item.checked);
const someChecked = items.some(item => item.checked) && !allChecked;

const toggleAll = () => {
  const newValue = !allChecked;
  setItems(items.map(item => ({ ...item, checked: newValue })));
};

const toggleItem = (id) => {
  setItems(items.map(item =>
    item.id === id ? { ...item, checked: !item.checked } : item
  ));
};

return (
  <div className="space-y-3">
    <div className="flex items-center space-x-2">
      <Checkbox
        id="select-all"
        checked={someChecked ? 'indeterminate' : allChecked}
        onCheckedChange={toggleAll}
      />
      <Label htmlFor="select-all" className="font-medium">
        Select all items
      </Label>
    </div>
    <div className="ml-6 space-y-2">
      {items.map(item => (
        <div key={item.id} className="flex items-center space-x-2">
          <Checkbox
            id={item.id}
            checked={item.checked}
            onCheckedChange={() => toggleItem(item.id)}
          />
          <Label htmlFor={item.id} className='font-normal'>{item.label}</Label>
        </div>
      ))}
    </div>
  </div>
);
}

Disabled State

Disabled Checkbox

Non-interactive checkbox

<div className="space-y-2">
<div className="flex items-center space-x-2">
  <Checkbox id="disabled-unchecked" disabled />
  <Label htmlFor="disabled-unchecked" className="font-normal text-ink-light">
    Disabled unchecked
  </Label>
</div>
<div className="flex items-center space-x-2">
  <Checkbox id="disabled-checked" disabled checked />
  <Label htmlFor="disabled-checked" className="font-normal text-ink-light">
    Disabled checked
  </Label>
</div>
</div>

With Description

Checkbox with Description

Additional context for the option

Receive tips, trends, and insights about email marketing.

<div className="flex items-start space-x-2">
<Checkbox id="marketing" className="mt-1" />
<div>
  <Label htmlFor="marketing" className='font-normal'>Marketing emails</Label>
  <p className="text-sm text-ink-light">
    Receive tips, trends, and insights about email marketing.
  </p>
</div>
</div>

Best Practices

Use clear labels

Labels should clearly describe what selecting the checkbox does. Use positive phrasing.

Group related options

Organize checkboxes logically and use a group label when presenting multiple related options.

Use indeterminate for parent items

When a parent checkbox controls child items, use the indeterminate state for partial selection.

Align labels consistently

Position labels consistently to the right of checkboxes for easy scanning.

Don't use for single binary choices

For immediate on/off toggles, use a Switch component instead.

Don't use for mutually exclusive options

When only one option can be selected, use Radio buttons instead.

Props

Checkbox

PropTypeDefaultDescription
checkedboolean | 'indeterminate'-Controlled checked state
defaultCheckedboolean-Default checked state
onCheckedChange(checked: boolean | 'indeterminate') => void-Change handler
disabledbooleanfalseDisable the checkbox
requiredbooleanfalseMark as required
namestring-Form field name
valuestring-Form value when checked
idstring-Element ID for label association
classNamestring-Additional className

Accessibility

Label Association

Always associate checkboxes with labels using the htmlFor attribute matching the checkbox id. This ensures proper accessibility and larger click targets.

  • Built on Radix UI Checkbox with full ARIA support
  • Supports keyboard activation with Space key
  • Communicates checked, unchecked, and indeterminate states to screen readers
  • Required state is announced by assistive technology
  • Focus ring provides clear visual feedback