# Toast

> Brief confirmation for a completed background action.

- Category: Messages
- Import: `import { Toast } from "@sagui/ui";`
- Page: /components/toast

```tsx
import { useState } from "react";
import { Button, Toast } from "@sagui/ui";

export function Hero() {
  const [open, setOpen] = useState(false);
  return (
    <div className="grid w-full place-items-center gap-5">
      <Button onClick={() => setOpen(true)} disabled={open}>Save project</Button>
      <div className="flex h-24 w-full items-end justify-center">
        <Toast open={open} onOpenChange={setOpen} title="Project saved" description="Closes itself, or swipe it away." />
      </div>
    </div>
  );
}
```

## When to use

- A single success confirmation, like Changes saved, controlled with local state.
- Demos or small apps that do not need a toast queue.

## When not to use

- Use alert for persistent messages that should stay in the page flow.

## Installation

Install the package and import the styles once. The [installation guide](/docs/installation) covers the Tailwind setup.

```bash
npm install @sagui/ui
```

## Usage

```tsx
import Toast from "@sagui/ui";

export function SavedToast() {
  const [open, setOpen] = useState(false);
  return (
    <>
      <button type="button" onClick={() => setOpen(true)}>Save</button>
      <Toast open={open} onOpenChange={setOpen} title="Changes saved" description="Synced to all devices." />
    </>
  );
}
```

## Examples

### Title only

```tsx
import { Toast } from "@sagui/ui";

export function TitleOnly() {
  return <Toast title="Link copied" />;
}
```

### Copy that changes

```tsx
import { useState } from "react";
import { Button, Toast } from "@sagui/ui";

export function Morphing() {
  const [done, setDone] = useState(false);
  return (
    <div className="grid w-full place-items-center gap-5">
      <Toast title={done ? "Upload complete" : "Uploading"} description={done ? "3 files are ready to share." : "This takes a few seconds."} />
      <Button variant="outline" size="sm" onClick={() => setDone((value) => !value)}>Toggle state</Button>
    </div>
  );
}
```

## API reference

### Toast

A single swipeable notification with a drawn check, auto-dismiss, and morphing copy. 

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `title` (required) | `string` | – | Headline. Changes crossfade while shown. |
| `description` | `string` | – | Supporting line. |
| `open` | `boolean` | `true` | Whether the toast is shown. Setting it true again after a dismiss re-raises it. |
| `onOpenChange` | `(open: boolean) => void` | – | Called with false on close, swipe, or timeout. Auto-dismiss only runs when this is provided. |
| `duration` | `number` | `4500` | Milliseconds before auto-dismiss. 0 or less disables it. |
| `className` | `string` | – | Added to the toast surface. |

## Keyboard interactions

| Keys | Action |
| --- | --- |
| Tab then Enter | Reaches and activates the dismiss button. |

## Accessibility

- Renders role="status" with aria-live="polite" and aria-atomic, so new content is announced without stealing focus.
- The dismiss button is labelled "Dismiss notification"; the check icon is aria-hidden.
- Positioning is up to the caller; the auto-dismiss timer does not pause on hover, so keep messages short.

## Motion

- Enters rising 16px from 0.96 scale on a morph spring while the check draws in; a swipe past 80px or 480px/s throws it off with its release velocity.
- Closing sinks it 8px and fades. Copy changes rise in while the height springs to fit.
- Reduced motion uses opacity fades and disables dragging.

## Responsive behavior

- The toast is min(100%, 26rem) wide and the title ellipsizes on one line.
- Positioning is up to you; fix it to the bottom center on phones so it clears the thumb zone edges.
- It swipes horizontally on touch and mouse; drag is disabled under reduced motion.

## Performance

- Drag and throw run on motion values, and a ResizeObserver springs the height when copy changes.
- The auto-dismiss timer does not pause on hover, so keep messages short.

## Notes

- Use for a single success confirmation you control with local state.
- Import as a default export. Position it yourself, for example fixed to the bottom of the viewport.

## Related

- [Alert](/components/alert): A persistent message that helps people recover or continue.
