import { Meta, Canvas, Controls } from '@storybook/addon-docs/blocks'
import * as CheckboxStories from './Checkbox.stories'

<Meta of={CheckboxStories} />

# Checkbox

A 16px square that fills with the accent when checked. Controlled only —
the parent owns the state.

<Canvas of={CheckboxStories.Toggles} />

## When

- A yes/no the person sets: an option in a form, an include/exclude in a
  list.
- Inside a clickable row: pass **no `onChange`**. The square then only
  draws the state: it is hidden from assistive technology and takes no
  focus, so the row is one control. The row says the state itself —
  `aria-pressed` on a button row, `aria-selected` on an option in a list.

<Canvas of={CheckboxStories.InsideARow} />

- With words beside it: pass **`label`**. The words are part of the
  target — clicking them toggles the box — and they name it, so no
  `aria-label` is needed.

<Canvas of={CheckboxStories.WithLabel} />

- A list you tick several from, where the whole row is the target: pass
  **`row`**, with `label` and, if the row has one, a `leading` picture. The
  box sits at the end, and the row fills on hover and while checked.

<Canvas of={CheckboxStories.Row} />

## When not

- One choice out of several → **Select** (a value) or **Tabs** (a view).
- A row drawn by hand with `role="option"` and a Checkbox picture inside it: it
  tells a screen reader "an option in a list" where there is no list. That is
  `row`.
- Inside a **Menu** — a checkbox inside a `menuitem` is invalid HTML;
  a checkable list lives in a DialogShell.

## How

```tsx
import { Checkbox } from '@estiva-app/ui'

<Checkbox checked={done} onChange={setDone} aria-label="Mark as done" />
```

- Built on Base UI Checkbox, as Base UI renders it: a `<span>` with
  `role="checkbox"` and `aria-checked`, and a hidden `<input>` beside it
  for forms. Its click never reaches the row around it.
- Give it an `aria-label`, or words of its own with `label`. Words written
  beside it by hand name nothing and toggle nothing; `label` does both.

```tsx
<Checkbox checked={on} onChange={setOn} label="Label" />
```

- With `label` it is Base UI's `Field`, its `Field.Label` around the box and
  the words: the box, 8px, then the words in `body-2`. `className` stays on
  the box. When disabled, only the box shows it; the words keep their colour
  and lose the pointer. It is a field of its own, so it does not go inside a
  **Field**.
- With `row` it is the same `Field`, its `Field.Label` the whole row:
  `leading`, 12px, the words in `body-2` (cut off with an ellipsis when too
  long), the box at the end; 40px tall, 12px in from each side, 8px corners.
  It needs `onChange`: without one, `row` is ignored. Put the rows in a
  column with `gap-0.5`.

```tsx
<Checkbox row leading={<IconSquareRounded size={16} stroke={1.5} />} label="Item one" checked={on} onChange={setOn} />
```

- Inside a busy **Form** it is disabled, and looks it.
- It does not move when it toggles: the tick is always in the box, hidden
  when unchecked, so both states hang on a line of text the same way.

## What it owns

It does these by itself. Write none of them around it.

| It does | So you never write | Refused when written by hand |
|---|---|---|
| Says what it is to assistive technology: a checkbox, ticked or not | `role="checkbox"` or `aria-checked` | ✓ |
| Toggles on Space and on a click; Enter is left to the form | a click or key handler |  |
| Is one Tab stop, in a `row` too | a `tabIndex` on the row |  |
| Keeps a `row`'s 40px in a scrolling column | `shrink-0` |  |

## Keys

| Key | Does |
|---|---|
| Tab | Onto the box (in a row too: the row is not a Tab stop of its own). |
| Space | Toggles it. |
| Enter | Nothing. As on a native checkbox, Enter is the form's key. |

## Props

<Controls of={CheckboxStories.Unchecked} />
