# Toast

Toast is a neobrutalist React component from Cruise UI. Feedback that pops up in a corner or edge you choose (bottom-right by default): copied, saved, something went wrong.

Install (with the @cruiseui registry in components.json, see Installation):

```bash
npx shadcn@latest add @cruiseui/toast
```

Import: `import { CruiseToast, CruiseToaster, useCruiseToast, CruiseToastViewport } from "@/components/cruise/toast";`

## When to use

All feedback after an action. Auto-dismiss after ~3s; errors stay until closed.

## When not to

Information people need to act on later (put it on the page). Never use alert().

## Usage

- Wrap your app in CruiseToaster once, then call useCruiseToast().toast({ title, description, tone, position }) anywhere.
- position is top-left, top-center, top-right, bottom-left, bottom-center or bottom-right (the default). Set it on the Toaster for every toast, or on one toast to override it.
- Top stacks grow down with the newest on top; bottom stacks grow up with the newest at the bottom. Below 640px every position is full width with 16px gutters.
- For your own toast (e.g. CruiseAchievementToast), pass render: (dismiss) => <YourToast onDismiss={dismiss} />.

## Example (React)

```tsx
"use client";

import { CruiseButton } from "@/components/cruise/button";
import { CruiseToast } from "@/components/cruise/toast";
import { CruiseToaster, useCruiseToast } from "@/components/cruise/toaster";

function SaveButtons() {
  const { toast } = useCruiseToast();
  return (
    <div className="flex flex-wrap gap-3">
      <CruiseButton variant="secondary" onClick={() => toast({ tone: "success", title: "Saved", description: "Your changes are live." })}>
        Save changes
      </CruiseButton>
      {/* One toast can go somewhere else. */}
      <CruiseButton
        variant="secondary"
        onClick={() => toast({ tone: "info", title: "Copied", description: "Link copied.", position: "bottom-center" })}
      >
        Copy link
      </CruiseButton>
    </div>
  );
}

export default function ToastExample() {
  return (
    // Wrap your app once; position: top-left | top-center | top-right |
    // bottom-left | bottom-center | bottom-right (default).
    <CruiseToaster position="top-right">
      <div className="flex flex-col gap-6">
        <SaveButtons />
        <CruiseToast tone="danger" title="Something went wrong">
          Try again.
        </CruiseToast>
      </div>
    </CruiseToaster>
  );
}
```

## HTML

Needs theme.css (https://cruiseui.dev/theme.css).

```html
<div class="toast-viewport" data-position="top-right">
  <div class="toast brutal" role="status" style="display: flex; overflow: hidden">
    <span style="width: 8px; background: var(--success)"></span>
    <div style="padding: 12px 16px"><strong>Done!</strong><br>Your ticket has been sent.</div>
  </div>
</div>
```

## Props: CruiseToast

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `tone?` | `CruiseToastTone` | `"info"` | — |
| `title` | `ReactNode` | — | — |
| `children?` | `ReactNode` | — | — |
| `onDismiss?` | `(() => void)` | — | — |
| `className?` | `string` | — | — |

## Props: CruiseToaster

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `position?` | `CruiseToastPosition` | `"bottom-right"` | Default spot for every toast; each toast can override it. |
| `children?` | `ReactNode` | — | — |

## Props: CruiseToastViewport

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `position?` | `CruiseToastPosition` | `"bottom-right"` | Where the stack sits. |
| `children` | `ReactNode` | — | — |

## Accessibility

- role="status" (role="alert" for danger), so screen readers announce it.
- The coloured left bar is backed by a title (Done!, Something went wrong).
- Errors stay until closed; under reduced motion toasts fade instead of sliding.
