# Toast

A succinct message that is displayed temporarily.

---

## Default

```tsx
import { Button, useToasts } from '@vercel/geistcn/components';
import type { JSX } from 'react';

export function Component(): JSX.Element {
  const toasts = useToasts();

  return (
    <Button
      onClick={(): void => {
        toasts.message({
          text: 'The Evil Rabbit jumped over the fence.',
        });
      }}
    >
      Show Toast
    </Button>
  );
}
```

## Multi-line

```tsx
import { Button, useToasts } from '@vercel/geistcn/components';
import type { JSX } from 'react';

export function Component(): JSX.Element {
  const toasts = useToasts();

  return (
    <Button
      onClick={(): void => {
        toasts.message({
          text: 'The Evil Rabbit jumped over the fence. The Evil Rabbit jumped over the fence. The Evil Rabbit jumped over the fence. The Evil Rabbit jumped over the fence.',
        });
      }}
    >
      Show Toast
    </Button>
  );
}
```

## With jsx

```tsx
import { Button, useToasts } from '@vercel/geistcn/components';
import type { JSX } from 'react';

export function Component(): JSX.Element {
  const toasts = useToasts();

  return (
    <Button
      onClick={(): void => {
        toasts.message({
          text: (
            <>
              <span className="text-heading-14">The Evil Rabbit</span> jumped
              over the fence.
            </>
          ),
          preserve: true,
        });
      }}
    >
      Show Toast
    </Button>
  );
}
```

## With a link

```tsx
import { Button, useToasts } from '@vercel/geistcn/components';

import { Link } from '@vercel/geistcn/components';
import type { JSX } from 'react';

export function Component(): JSX.Element {
  const toasts = useToasts();

  return (
    <Button
      onClick={(): void => {
        toasts.message({
          text: (
            <>
              The Evil Rabbit jumped over the fence. The Evil Rabbit jumped over
              the{' '}
              <Link data-zone="same" href="/geist" isDifferentZone={false}>
                fence again
              </Link>
              .
            </>
          ),
          preserve: true,
        });
      }}
    >
      Show Toast
    </Button>
  );
}
```

## Preserve

```tsx
import { Button, useToasts } from '@vercel/geistcn/components';
import type { JSX } from 'react';

export function Component(): JSX.Element {
  const toasts = useToasts();

  return (
    <Button
      onClick={(): void => {
        toasts.message({
          text: 'The Evil Rabbit jumped over the fence.',
          preserve: true,
        });
      }}
    >
      Show Toast
    </Button>
  );
}
```

## Action

```tsx
import { Button, useToasts } from '@vercel/geistcn/components';
import type { JSX } from 'react';

export function Component(): JSX.Element {
  const toasts = useToasts();

  return (
    <Button
      onClick={(): void => {
        toasts.message({
          text: 'The Evil Rabbit jumped over the fence. The Evil Rabbit jumped over the fence again.',
          action: 'Undo',
        });
      }}
    >
      Show Toast
    </Button>
  );
}
```

## Undo

```tsx
import { Button, useToasts } from '@vercel/geistcn/components';
import type { JSX } from 'react';

export function Component(): JSX.Element {
  const toasts = useToasts();

  return (
    <Button
      onClick={(): void => {
        toasts.message({
          text: 'The Evil Rabbit jumped over the fence. The Evil Rabbit jumped over the fence again.',
          onUndoAction: () => 0,
        });
      }}
    >
      Show Toast
    </Button>
  );
}
```

## Success

```tsx
import { Button, useToasts } from '@vercel/geistcn/components';
import type { JSX } from 'react';

export function Component(): JSX.Element {
  const toasts = useToasts();

  return (
    <Button
      onClick={(): void => {
        toasts.success('The Evil Rabbit jumped over the fence.');
      }}
    >
      Show Toast
    </Button>
  );
}
```

## Warning

```tsx
import { Button, useToasts } from '@vercel/geistcn/components';
import type { JSX } from 'react';

export function Component(): JSX.Element {
  const toasts = useToasts();

  return (
    <Button
      onClick={(): void => {
        toasts.warning('The Evil Rabbit jumped over the fence.');
      }}
    >
      Show Toast
    </Button>
  );
}
```

## Error

```tsx
import { Button, useToasts } from '@vercel/geistcn/components';
import type { JSX } from 'react';

export function Component(): JSX.Element {
  const toasts = useToasts();

  return (
    <Button
      onClick={(): void => {
        toasts.error('The Evil Rabbit jumped over the fence.');
      }}
    >
      Show Toast
    </Button>
  );
}
```

## Best Practices

### When to use

* Use a toast for non-blocking acknowledgments of user-initiated actions: `Domain added`, `Project archived`, `Deployment canceled`.
* Don’t use a toast alone for billing failures, permission denials, or build failures the user has to triage. Pair a ≤6-word toast (`Build failed`) with a persistent row carrying the recovery step and a stable identifier.
* Field-level validation belongs on the `Input`, not in a toast. Persistent configuration warnings belong in `Note` or `Banner`.
* Pick the method by how the user experienced the event, not by HTTP status. A user-canceled deploy is `toasts.message('Deployment canceled')`, not `success`. A partial deploy with skipped routes is `toasts.warning(...)`.

### Behavior

* Default toasts auto-dismiss; pass `preserve` only when the user must read or act on the message before it disappears.
* Undo snackbars stay on screen for 5–10 seconds and pair the past-tense toast with a single `Undo` action button.
* Don’t stack toasts to narrate one async flow; emit the success or error toast at the terminal step.

### Content

* One sentence, sentence case, no trailing period when the toast is a single sentence.
* Completion toasts follow `{Noun} {past-participle}`: `Blob deleted`, `Domain added`, `Environment variable saved`. Never include `successfully`; the action name implies it.
* Error toasts are two sentences with periods and end with a recovery step: `Couldn’t verify domain. Try again.` Use `Couldn’t` for user-state errors and `Failed to` for system or infra errors; match adjacent shipped copy and don’t flip mid-flow.
* Pair the toast verb 1:1 with the destructive button verb (`Delete Project` then `Project deleted`, never `Project removed`).
* Undo snackbars use the literal label `Undo`, never `Restore`, `Bring Back`, or `Cancel`. Only use the pattern when the rollback is safe.

### Accessibility

* The toast region announces with `aria-live="polite"`; reserve `assertive` for blocking errors that interrupt a flow.
* Don’t put primary navigation inside a toast; transient surfaces vanish before keyboard users can reach them.
