# Toast

Show temporary feedback with dismissible notifications.

Toast with title and description

[Complete TSX file](/examples/toast/default.tsx)

```tsx
"use client";

import { Button } from "@/siteplane/components/button";
import { ToastPrimitive, ToastProvider } from "@/siteplane/components/toast";
import { useState } from "react";

export default function Example() {
  const [manager] = useState(() => ToastPrimitive.createToastManager());
  return (
    <ToastProvider toastManager={manager}>
      <Button
        variant="outline"
        onClick={() =>
          manager.add({
            title: "Changes saved",
            description: "Your preferences are up to date.",
          })
        }
      >
        Show toast
      </Button>
    </ToastProvider>
  );
}
```

## Installation

Complete [one-time setup](/docs/installation/) first.

```bash
pnpm dlx shadcn@4.18.0 add @siteplane/toast
```

With npm: `npx shadcn@4.18.0 add @siteplane/toast`. [Registry JSON](/registry/toast.json) lists source files and dependencies.

For this page’s examples, also install:

```bash
pnpm dlx shadcn@4.18.0 add @siteplane/button
```

## Usage

```tsx
import { Button } from "@/siteplane/components/button";
import { ToastProvider, toastManager } from "@/siteplane/components/toast";

<ToastProvider>
  <Button onClick={() => toastManager.add({ title: "Saved", type: "success" })}>
    Save
  </Button>
</ToastProvider>;
```

## Composition

```text
ToastProvider
  Application content
  (managed portal, viewport, toast cards)
```

## Types

Set `type` to add a status icon: success, info, warning and error. State the outcome in the title as well.

Toast types

[Complete TSX file](/examples/toast/types.tsx)

```tsx
"use client";

import { Button } from "@/siteplane/components/button";
import { ToastPrimitive, ToastProvider } from "@/siteplane/components/toast";
import { useState } from "react";

const toasts = [
  {
    label: "Success",
    type: "success",
    title: "Project created",
    description: "Website redesign is ready for your team.",
  },
  {
    label: "Info",
    type: "info",
    title: "New comment",
    description: "Ben replied to your review.",
  },
  {
    label: "Warning",
    type: "warning",
    title: "Storage almost full",
    description: "Your workspace has used 90% of its storage.",
  },
  {
    label: "Error",
    type: "error",
    title: "Payment failed",
    description: "Update your card to keep your subscription active.",
  },
];

export default function Example() {
  const [manager] = useState(() => ToastPrimitive.createToastManager());
  return (
    <ToastProvider toastManager={manager}>
      <div className="flex flex-wrap gap-2">
        {toasts.map(({ label, ...toast }) => (
          <Button
            key={toast.type}
            variant="outline"
            onClick={() => manager.add(toast)}
          >
            {label}
          </Button>
        ))}
      </div>
    </ToastProvider>
  );
}
```

## Promise

Use `promise()` to move one toast from loading to success or error when the task settles. A loading toast shows the [Spinner](/docs/components/spinner/) in place of an icon and stays open until it is updated or closed. This example resolves a timer instead of running a real export.

Export progress toast

[Complete TSX file](/examples/toast/update.tsx)

```tsx
"use client";

import { Button } from "@/siteplane/components/button";
import { ToastPrimitive, ToastProvider } from "@/siteplane/components/toast";
import { useState } from "react";

export default function Example() {
  const [manager] = useState(() => ToastPrimitive.createToastManager());
  return (
    <ToastProvider toastManager={manager}>
      <Button
        variant="outline"
        onClick={() => {
          manager.promise(
            new Promise<void>((resolve) => {
              window.setTimeout(resolve, 2000);
            }),
            {
              loading: { title: "Exporting report…" },
              success: {
                title: "Report exported",
                description: "The CSV file is ready to download.",
              },
              error: {
                title: "Could not export report",
                description: "Try again in a moment.",
              },
            },
          );
        }}
      >
        Export report
      </Button>
    </ToastProvider>
  );
}
```

Keep the id returned by `add()` to change a toast later with `update(id, options)` or to remove it with `close(id)`. Passing an existing `id` to `add()` updates that toast in place instead of stacking another. Each update replays a short pulse, or a shake for errors, unless reduced motion is on.

## Action

Pass `actionProps` to render an action button next to the message. Your application performs the operation and its reversal; this example only closes the toast.

Toast with undo action

[Complete TSX file](/examples/toast/action.tsx)

```tsx
"use client";

import { Button } from "@/siteplane/components/button";
import { ToastPrimitive, ToastProvider } from "@/siteplane/components/toast";
import { useState } from "react";

export default function Example() {
  const [manager] = useState(() => ToastPrimitive.createToastManager());
  return (
    <ToastProvider toastManager={manager}>
      <Button
        variant="outline"
        onClick={() => {
          const id = manager.add({
            title: "Project archived",
            description: "Website redesign moved to the archive.",
            actionProps: {
              children: "Undo",
              onClick: () => manager.close(id),
            },
          });
        }}
      >
        Show toast
      </Button>
    </ToastProvider>
  );
}
```

## API reference

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| ToastProvider.position | ToastPosition | "bottom-right" | top-left, top-center, top-right, bottom-left, bottom-center, bottom-right. |
| ToastProvider.toastManager | ReturnType<typeof ToastPrimitive.createToastManager> | Exported toastManager singleton | Use one provider per manager; examples use isolated local managers. Providers that share a manager draw one stack. |
| ToastProvider.portalProps | ToastPrimitive.Portal props | — | Forwarded to the portal. |
| ToastProvider.dismissLabel | string | Dismiss toast | Accessible name of the dismiss button of every toast of the provider. |
| ToastProvider children / timeout / limit | ToastPrimitive.Provider props | Foundation defaults | Provider content, default lifetime, and visible stack limit. |
| toastManager | Toast manager | Module singleton | add returns an id; update(id, options), close(id), promise and subscribe follow the foundation API. |
| ToastPrimitive | Base UI Toast namespace | — | Unstyled foundation parts and createToastManager. |
| Toast object type | string | — | success, error, info and warning show a status icon; loading shows the Spinner. |
| Toast object data.content | ReactNode | — | Custom body inside the existing toast lifecycle. Supply a title for its accessible announcement; close, timing and stacking remain owned by Toast. |
| Toast object data.rootProps | ToastPrimitive.Root props | — | Root overrides except children, className, swipeDirection and toast. |

Exported types: `ToastProviderProps`, `ToastData`. These describe the contracts above.

[Read the installed source](/source/toast).

## Usage notes

Mount the shared provider once near your application root. Position determines permitted swipe-dismiss directions. Each toast has a dismiss button. See the exact inherited [Base UI Toast API](https://base-ui.com/react/components/toast) for add/update options, priorities, callbacks, promise handling, timeout, and limit. Do not use toast as the only place to expose persistent form errors.

Each provider keeps its own toasts. When several providers use one position, as the examples on this page do, their stacks sit one above the other: the stack that received a toast last takes the edge and the others stand back, so every front toast stays readable. Reduced motion makes the stacks move at once.
