# Checkbox

> Slug: `checkbox` · Category: Form Controls

## When to use

- Binary opt-in: terms acceptance, marketing consent, "remember me".
- A list of independent boolean choices ("Notify me about: Email / SMS / Push").
- Indeterminate state for "select all" controls over a list.

## When NOT to use

- Mutually exclusive options — use `RadioGroup` or `StyledRadioGroup`.
- An on/off setting that toggles immediately — use `Toggle`.
- Filterable tag selection — use `Chips variant="toggle"`.

## Variants & decision tree

| Need | Prop |
|---|---|
| Standard | (default) |
| Smaller compact label | `labelSize="small"` |
| "Select all" tri-state | `indeterminate` |
| Inline link in label | `link={{ text, url }}` or `links={[...]}` |
| Validation error | `invalid` + `errorMessage` |

## States

Unchecked, checked, indeterminate, focused, hover, pressed, disabled, invalid (with error message).

## Props

| Prop | Type | Default | Description |
|---|---|---|---|
| `id` | `string` | — | Required. Unique input id. |
| `name` | `string` | — | Required. Form name. |
| `label` | `ReactNode` | — | Required. Visible label. |
| `checked` / `defaultChecked` | `boolean` | — | Controlled / uncontrolled state. |
| `onChange` | `ChangeEventHandler` | — | Use `e.target.checked`. |
| `labelSize` | `'large' \| 'small'` | `'large'` | Visual label size. |
| `indeterminate` | `boolean` | `false` | Tri-state visual. |
| `invalid` | `boolean` | `false` | Sets error styling. |
| `errorMessage` | `string` | — | Shown when `invalid`. |
| `link` | `{ text, url?, onClick? }` | — | Single inline link in label. |
| `links` | `CheckboxLink[]` | — | Multiple inline links. |
| `linkDisabled` | `boolean` | `false` | Mute link styling when disabled. |
| `inverse` | `boolean` | `false` | Dark-background styling. |
| `disabled` | `boolean` | `false` | Disables input. |

## Usage examples

```tsx
// Standard opt-in
<Checkbox id="terms" name="terms" label="I agree to the terms" checked={agreed} onChange={(e) => setAgreed(e.target.checked)} />

// With inline links
<Checkbox
  id="legal"
  name="legal"
  label="I agree to the"
  links={[
    { text: 'Terms', url: '/terms' },
    { text: 'Privacy Policy', url: '/privacy' },
  ]}
/>

// Indeterminate "select all"
<Checkbox id="all" name="all" label="Select all" indeterminate={someSelected} checked={allSelected} onChange={toggleAll} />
```

## Composition

Group multiple checkboxes inside a `<fieldset>` with a `<legend>` if they form a related set. Use a single Checkbox for standalone consent.

## Accessibility

`id`, `name`, and `label` are required. `indeterminate` is rendered via the input property — screen readers announce "mixed". Use `errorMessage` with `invalid` for inline validation; the message is wired with `aria-describedby`.

## Do / Don't

- DO group related checkboxes inside a fieldset with a legend.
- DO use `indeterminate` for parent "select all" controls.
- DON'T use a checkbox for mutually exclusive choice — use `RadioGroup`.
- DON'T toggle navigation or settings instantly — that's `Toggle`'s job.
