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

<Meta of={ButtonStories} />

# Button

The push-button for an action: a verb, clicked once — "Create", "Save",
"Delete". Four variants on one geometry: 32px default / 24px small,
6px radius, medium weight.

<Canvas of={ButtonStories.AllVariants} />

## When

- **`primary`** — the one action the surface exists for. At most one per
  surface. It reads in `text-inverse` on the accent; the theme decides what
  both of those are.
- **`outlined`** — a real alternative standing beside the primary ("Cancel"
  next to "Save"), or a lone action that needs an edge to be found at all.
- **`muted`** — the default, and most buttons. Anything that should not
  compete for attention: dialog dismissals, secondary page actions.
- **`destructive`** — "Delete …" and its kind: the muted button in the
  error colour. A destructive action is a button like any other, not a
  dotted link — it is guarded by a ConfirmDialog, not by being hard to see.

## When not

- An icon with no label → **IconButton**.
- Going somewhere rather than doing something → **Link**; **Tabs** or
  **Breadcrumb** when it is a view or a trail.
- Choosing a value → **Select**. Acting from a popover list → **MenuItem**.
- A control the person may never be allowed to use is **absent, not
  disabled**. `disabled` is for *momentarily* unavailable — and it says why,
  with `disabledReason` ("Available after sign-in"). A send button waiting for
  its fields needs no reason.

## How

```tsx
import { Button } from '@estiva-app/ui'
import { IconPlus } from '@tabler/icons-react'

<Button variant="primary" leadingIcon={<IconPlus stroke={1.5} className="size-4" />} onClick={create}>
  New document
</Button>
```

- `leadingIcon` is 16px at stroke 1.5 (14px, `size-3.5`, on `small`); the
  button balances its own padding around it.
- `type` defaults to `"button"` — inside a form it submits only when you
  say `type="submit"`.
- It is a native `<button>` on Base UI's Button, and every native prop
  passes through; the visible label is the accessible name, so no
  `aria-label` is needed.
- `disabledReason="Sign in first"` disables it, keeps it reachable by
  Tab, and shows the reason as a tooltip. Say why, every time; a bare
  `disabled` is for the moment between a click and its answer. **The
  reason shows on keyboard focus as well as on hover**, which is what
  makes it worth writing: a reason only a mouse can read is not offered
  to everyone. The button itself is the tooltip's trigger, so it wears no
  wrapper — what a caller gets is the `<button>`, and a `Menu.Trigger` or
  a `Dialog.Close` can be it.

- `variant="resolve"` is `primary` in every theme but Signal, where it is
  outlined at rest and green when pointed at — the Resolve button. `IconButton`
  has the same look.
- **Placed from outside, never restyled.** `className` takes space, size,
  flex and grid, and position; a colour, a text size, a border, a corner or a
  shadow is refused by the lint (`estiva/no-restyled-part`).

## 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 button | `role="button"` | ✓ |
| Is reachable with Tab, also when it is disabled with a reason | a `tabIndex` | ✓ |
| Presses on Enter and Space, and does nothing while disabled | a key handler |  |
| Keeps its 32px (24px small) in a scrolling column | `shrink-0` |  |

## Keys

| Key | Does |
|---|---|
| Tab | Onto the button, also when it is disabled with a reason; never when it is plain `disabled`. |
| Space / Enter | The action. Nothing while disabled. |

## Props

<Controls of={ButtonStories.Primary} />
