Components

Checkbox

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

Installation

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

Usage

Import the Checkbox component from the package:

import { Checkbox, Label } from '@marmoui/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