# Checkbox

A 16px box that turns one option on or off, or shows that a group is partly on. Sunken with the control border when off; the accent with a check when on, or a minus when partly on. label puts its name after it, and description a second line under the name.

## Usage

### When to use

- Turn one option on or off when the change takes effect on save, such as accepting the terms.
- Pick any number of items from a list, such as rows in a table, each with its own box.

### When not to use

- A setting that applies at once, such as dark mode. Use Switch.
- Picking exactly one of several options. Use RadioGroup, or Select for a long list.
- Running an action, such as deleting the selected rows. Use Button.

## Variants

### checked

Controlled state: true, false or "indeterminate" (partly on). Pair it with onCheckedChange.

Values: `false`, `true`, `indeterminate`. Default: `false`.

## Examples

### Default

```tsx
<Checkbox label="Email me product updates" />
```

### With a description

The description is read after the name.

```tsx
<Checkbox
  label="Weekly digest"
  description="A summary of your team's activity, every Monday."
  defaultChecked
/>
```

### Required

The form can't be sent until the box is on. The asterisk is on the label; required on the box is what screen readers announce.

```tsx
<Checkbox label="I accept the terms" required />
```

### Partly on

A box that selects every row, while only some rows are selected. The table shows the name, so the box takes aria-label.

```tsx
<Checkbox defaultChecked="indeterminate" aria-label="Select all rows" />
```

### Disabled

```tsx
<Checkbox
  label="Sign in with SSO"
  description="Your admin turned this on for everyone."
  disabled
  defaultChecked
/>
```

## Do and don't

### Do

- Name it with the label prop; add a description when the name alone doesn't say what turning it on does.
- Use it for a choice that takes effect when the form is saved, or to pick several items.
- Use partly on for a box that selects a list of which only some items are on.

### Don't

- Don't use it for a setting that applies at once; use Switch.
- Don't use it to pick exactly one of several options; use RadioGroup.
- Don't put the name before the box, or the description inside the label.

## Props

| Name | Type | Values | Default | Description |
| --- | --- | --- | --- | --- |
| `label` | `node` |  |  | The visible name, after the box. A press on it toggles the box. Short, sentence case: Email me product updates. |
| `description` | `node` |  |  | A second line under the label: what turning it on does. Needs label. |
| `checked` | `enum` | `false`, `true`, `indeterminate` | `false` | Controlled state: true, false or "indeterminate" (partly on). Pair it with onCheckedChange. |
| `defaultChecked` | `boolean` |  | `false` | On at first render, when you don't control it. Also takes "indeterminate". |
| `onCheckedChange` | `function` |  |  | Called with true or false when the user toggles the box. |
| `disabled` | `boolean` |  | `false` | Can't be focused or toggled. Disable its Label too. |
| `required` | `boolean` |  | `false` | Must be on to submit the form, such as accepting the terms. Mark its Label required too. |
| `name` | `string` |  |  | Form name. The form submits value under this name while the box is on. |
| `value` | `string` |  | `on` | Value submitted while the box is on. |

## Anatomy

| Part | Description |
| --- | --- |
| `root` | The box: 16px, radius-inner, control border on the sunken fill. On and partly on, the accent fills it to the edge. |
| `icon` | The check (on) or the minus (partly on): Tabler, 16px, in the on-accent icon color. |
| `hitArea` | Transparent ::before centered on the box, never smaller than size-target-min (24px on mouse, 44px on touch). |
| `label` | With label: a Label after the box, level with the box on its first line. It follows required and disabled. |
| `description` | With description: 13px secondary text under the label, gap-xs. |
| `row` | With label: the row that holds the box, then the Label and the description, gap-sm. RadioGroup and Switch share it. |

## Accessibility

Role: `checkbox`

| Keys | Action |
| --- | --- |
| `Space` | Turns the box on or off. A partly on box turns on. |
| `Tab` | Moves focus to the next box; each checkbox is its own tab stop. |

- Name every box: the label prop (a press on it toggles the box), or aria-label when the name is shown elsewhere, such as a row in a table. A separate Label with htmlFor also works when the layout needs it.
- description is linked with aria-describedby and sits outside the label element, so screen readers read it after the name instead of as part of it.
- Partly on is aria-checked="mixed", for a box that selects a list of which only some items are on.
- Enter does not toggle a checkbox, as in a native one: it submits the form.
- The box is 16px but its hit area is size-target-min (24px on mouse, 44px on touch).
- Inside a form, a hidden input carries name and value, so the form submits it like a native checkbox.
- On and off differ by the check or minus as well as the fill, so the state never relies on color alone.

## Install

```bash
npx shadcn add https://werewolf-ui.vercel.app/r/checkbox.json
```

This also adds `styles/werewolf.css`, the tokens every component uses, and any other component it needs. Import that file once in your root CSS, after `@import "tailwindcss"`, with a path relative to that CSS file (from `app/globals.css` it is `@import "../styles/werewolf.css"`).
