MiHCM
primitives/@mihcm/ui·v0.21.0·stable

Checkbox

Controlled checkbox with three states — true, false, "indeterminate". aria-checked="mixed" for indeterminate.

In context

Four realistic surfaces — task list with strikethrough completion, terms-of-service gate, faceted filter list, and table row selection with indeterminate "select all".

Today's tasks

Strikethrough on complete.

2 / 5

Before we continue

Required + optional consent.

Department

Faceted multi-select with running counts.

84
24
41
18
9

Selected rows

0 selected

Indeterminate state when partial selection.

Yashi EL
Yashi EL
yashi@mihcm.com
Lead
Marcus Reid
Marcus Reid
marcus.reid@mihcm.com
Senior
Priya Anand
Priya Anand
priya.anand@mihcm.com
Senior

Basic with label

import { useState } from 'react';
import { Checkbox } from '@mihcm/ui/Checkbox';
import { Label } from '@mihcm/ui/Label';
 
const [checked, setChecked] = useState(false);
 
<div className="flex items-center gap-2">
  <Checkbox id="terms" checked={checked} onCheckedChange={setChecked} />
  <Label htmlFor="terms">I agree to the terms of service</Label>
</div>

Indeterminate state

Use "indeterminate" for a parent checkbox when only some children are selected.

import { useState } from 'react';
import { Checkbox, type CheckedState } from '@mihcm/ui/Checkbox';
import { Label } from '@mihcm/ui/Label';
 
const [items, setItems] = useState([true, false, true]);
const allChecked = items.every(Boolean);
const someChecked = items.some(Boolean);
const parentState: CheckedState = allChecked
  ? true
  : someChecked
    ? 'indeterminate'
    : false;
 
<div className="space-y-2">
  <div className="flex items-center gap-2">
    <Checkbox
      id="select-all"
      checked={parentState}
      onCheckedChange={() => setItems(items.map(() => !allChecked))}
    />
    <Label htmlFor="select-all">Select all</Label>
  </div>
  {items.map((val, i) => (
    <div key={i} className="flex items-center gap-2 pl-6">
      <Checkbox
        id={`item-${i}`}
        checked={val}
        onCheckedChange={(v) => {
          const next = [...items];
          next[i] = v === true;
          setItems(next);
        }}
      />
      <Label htmlFor={`item-${i}`}>Item {i + 1}</Label>
    </div>
  ))}
</div>

Disabled

<div className="flex items-center gap-2">
  <Checkbox id="disabled" checked={false} onCheckedChange={() => {}} disabled />
  <Label htmlFor="disabled">Cannot change this</Label>
</div>