Siteplane UI

Toast

Show temporary feedback with dismissible notifications.

Markdown
"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

pnpm dlx shadcn@4.18.0 add @siteplane/toast

Complete the one-time setup first. Registry JSON lists source files and dependencies.

For this page’s examples, also install:

pnpm dlx shadcn@4.18.0 add @siteplane/button

Usage

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

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.

"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 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.

"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.

"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

Component properties
PropTypeDefaultDescription
ToastProvider.positionToastPosition"bottom-right"top-left, top-center, top-right, bottom-left, bottom-center, bottom-right.
ToastProvider.toastManagerReturnType<typeof ToastPrimitive.createToastManager>Exported toastManager singletonUse one provider per manager; examples use isolated local managers. Providers that share a manager draw one stack.
ToastProvider.portalPropsToastPrimitive.Portal props—Forwarded to the portal.
ToastProvider.dismissLabelstringDismiss toastAccessible name of the dismiss button of every toast of the provider.
ToastProvider children / timeout / limitToastPrimitive.Provider propsFoundation defaultsProvider content, default lifetime, and visible stack limit.
toastManagerToast managerModule singletonadd returns an id; update(id, options), close(id), promise and subscribe follow the foundation API.
ToastPrimitiveBase UI Toast namespace—Unstyled foundation parts and createToastManager.
Toast object typestring—success, error, info and warning show a status icon; loading shows the Spinner.
Toast object data.contentReactNode—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.rootPropsToastPrimitive.Root props—Root overrides except children, className, swipeDirection and toast.

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

Read the installed source.

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 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.