# Alert

A message about the page, in place.

- Group: Feedback
- Import: `import { Alert } from '@misoto22/folio'`
- Page: https://ui.misoto22.com/components/alert/
- Related: toast, error-state

## When to reach for it

Something the reader needs to see and may need to act on. Something they only need to notice is a Toast.

## Anatomy

- **Region** (required) — The container, carrying the role and the aria-live the tone chooses, plus the tone’s ground. It is not focusable and it is not a landmark, so it exists for the reader who is already there and for the announcement.
- **Mark** — The tone’s Remix Icon glyph at 18px — RiInformationLine, RiCheckboxCircleLine, RiAlertLine or RiCloseCircleLine — aria-hidden, so it doubles the colour for sighted readers only. hideIcon removes it.
- **Title** — title, as a medium-weight paragraph in --ink. A p and not a heading, so it never appears in a screen reader’s heading list.
- **Body** — children, in --ink-2 at relaxed leading, offset from the title only when there is a title to offset from.
- **Action** — action, below the body and inside the region — so its label is read out with the message rather than being something the reader has to go looking for.

## Best practices

### Do

- Mount the Alert when there is something to say and unmount it when there is not. A region kept permanently in the page announces only when its words change, so a second failed submit carrying the same message is announced to nobody.
- Move focus after a failed submit — to the Alert or to the field it names. The component announces and then stays put, so a keyboard reader hears the error from wherever they were standing and has no way back to it.
- Put the retry, the link or the escape in action rather than describing it in the prose. It sits inside the live region, which is the difference between the announcement telling the reader what to do and merely telling them something is wrong.

### Don’t

- hideIcon takes away one of the two things that double the colour, and the tinted grounds are 13–16% alpha over paper. With the mark gone the severity is carried by a wash the reader may not resolve at all, so the words have to say it outright.
- info is the default and the only tone with a border and no tint — --paper-2 inside a --rule-2 hairline, which is a card. An Alert written without tone therefore looks like page furniture rather than like a notice.
- Do not stack alerts as a running log. Each one is its own live region, so five on a page are five announcements competing for the same speech queue, and a danger among them is assertive enough to cut off the four that explain it.

## Accessibility

- danger is role="alert" and interrupts; the other three are role="status" and wait for a pause.
- Colour is doubled by an icon and by the words.

## Alert

A message about the page, in place. Carries `role="alert"` for the danger tone and `role="status"` for the rest, which is the difference between interrupting the reader and waiting for a pause. Getting that backwards is the usual accessibility failure here: a "saved" toast that talks over someone mid-sentence, or a payment error that is never announced at all. The tone is the message's SEVERITY, not its decoration. Colour is doubled by an icon and by the words, so the meaning survives both monochrome printing and colour-blindness.

### Props

- `tone` — `AlertTone` default `'info'`.
- `title` — `ReactNode`.
- `children` — `ReactNode`.
- `action` — `ReactNode`. Optional action — a retry, a link to the settings that fix this.
- `hideIcon` — `boolean` default `false`. Hides the leading icon for a dense inline notice.

Also accepts: `Omit<HTMLAttributes<HTMLDivElement>, 'title'>`.

## Example — tones

```tsx
import { Alert, Button } from '@misoto22/folio'

<div className="flex w-full flex-col gap-3">
  <Alert title="Read-only mode">A migration is running; edits are paused until it finishes.</Alert>
  <Alert tone="success" title="Deployed">misoto22-site is live at commit a1b2c3d.</Alert>
  <Alert tone="warning" title="Token expires in 6 days">Rotate it before the next release.</Alert>
  <Alert
    tone="danger"
    title="Upload failed"
    action={<Button size="sm" variant="secondary">Try again</Button>}
  >
    The file exceeds the 25 MB limit.
  </Alert>
</div>
```

## Example — a failed submit

```tsx
import { Alert, Button, Field, Input } from '@misoto22/folio'

<div className="flex w-full max-w-sm flex-col gap-5">
  <Alert
    tone="danger"
    title="We could not send the invitation"
    action={<Button size="sm" variant="secondary">Try again</Button>}
  >
    The address bounced when we checked it.
  </Alert>
  <Field label="Email" error="Enter an address we can deliver to.">
    <Input defaultValue="henry@exmaple.com" />
  </Field>
</div>
```

## Example — inside the panel

```tsx
import { Alert, Button, Card, CardBody, CardHeader, CardTitle } from '@misoto22/folio'

<Card className="w-full max-w-md">
  <CardHeader>
    <CardTitle>Deploy history</CardTitle>
  </CardHeader>
  <CardBody>
    <Alert
      tone="warning"
      title="History is unavailable"
      action={<Button size="sm" variant="secondary">Reload</Button>}
    >
      The build log service did not answer. Everything else on this page is current.
    </Alert>
  </CardBody>
</Card>
```
