PRIZM 4.0DSTA
All components

Toast

Transient notification.

stableBase UI Toast

Preview

Code

tsx
import { Button } from "@/components/ui/button";
import { toast } from "@/components/ui/toast";

export function Example() {
  return (
    <div className="flex flex-wrap gap-2">
      <Button
        variant="outline"
        size="sm"
        onClick={() =>
          toast.add({
            title: "Saved",
            description: "Your changes have been saved.",
            type: "success",
          })
        }
      >
        Success
      </Button>
      <Button
        variant="outline"
        size="sm"
        onClick={() =>
          toast.add({
            title: "Couldn't save",
            description: "Network error. Try again.",
            type: "error",
          })
        }
      >
        Error
      </Button>
      <Button
        variant="outline"
        size="sm"
        onClick={() =>
          toast.add({
            title: "Heads up",
            description: "A new version is available.",
            type: "info",
          })
        }
      >
        Info
      </Button>
    </div>
  );
}

// <ToastProvider> must wrap your app in app/layout.tsx.

Props

No props on the root — see sub-components below.

Sub-components

ToastProviderWraps the app. Required for `toast.add()` calls to render.
ToastViewportWhere toasts appear. Rendered inside ToastProvider by default.

Built on Base UI Toast. Trigger via the imperative `toast.add({ title, description, variant })` singleton from `components/ui/toast.tsx`. `<ToastProvider>` must be in `app/layout.tsx` for toasts to render.

All components also accept standard HTML attributes for their root element (e.g. `id`, `aria-*`, `data-*`, event handlers) and forward `ref` where applicable.

Source

The full implementation of components/ui/toast.tsx is below — copy it into your project and own it. Some components import the cn helper from lib/utils or other primitives; copy those too.

tsx
"use client";

import { cn } from "@/lib/utils";
import { Toast as BaseToast } from "@base-ui-components/react/toast";
import { AlertCircle, CheckCircle, Info, X } from "lucide-react";
import type { ComponentPropsWithoutRef, ReactNode } from "react";

// Singleton manager — import `toast` and call toast.add(), toast.promise(), etc.
export const toast = BaseToast.createToastManager();

const typeIcons: Record<string, ReactNode> = {
  success: <CheckCircle className="h-4 w-4 text-success" />,
  error: <AlertCircle className="h-4 w-4 text-danger" />,
  info: <Info className="h-4 w-4 text-info" />,
};

function ToastViewportInner() {
  const { toasts } = BaseToast.useToastManager();
  return (
    <BaseToast.Viewport
      className={cn(
        "fixed bottom-4 right-4 z-50 flex max-h-screen w-full max-w-sm flex-col-reverse gap-2",
        "sm:bottom-4 sm:right-4",
      )}
    >
      {toasts.map((t) => (
        <BaseToast.Root
          key={t.id}
          toast={t}
          className={cn(
            "relative flex w-full items-start gap-3 overflow-hidden rounded-lg border border-border",
            "bg-surface-elevated p-4 shadow-lg",
            "data-[starting-style]:translate-y-2 data-[starting-style]:opacity-0",
            "data-[ending-style]:translate-y-2 data-[ending-style]:opacity-0",
            "transition-all duration-200",
          )}
        >
          {t.type && typeIcons[t.type] && (
            <div className="mt-0.5 shrink-0">{typeIcons[t.type]}</div>
          )}
          <div className="flex flex-1 flex-col gap-0.5">
            {t.title && <BaseToast.Title className="text-sm font-semibold text-fg" />}
            {t.description && <BaseToast.Description className="text-sm text-fg-muted" />}
          </div>
          <BaseToast.Close
            className={cn(
              "mt-0.5 shrink-0 rounded-sm text-fg-muted opacity-70 transition-opacity",
              "hover:opacity-100 focus-visible:outline-1 focus-visible:outline-offset-0 focus-visible:outline-accent",
            )}
            aria-label="Dismiss"
          >
            <X className="h-4 w-4" />
          </BaseToast.Close>
        </BaseToast.Root>
      ))}
    </BaseToast.Viewport>
  );
}

export function ToastProvider({
  children,
  timeout = 5000,
}: {
  children: ReactNode;
  timeout?: number;
}) {
  return (
    <BaseToast.Provider toastManager={toast} timeout={timeout}>
      {children}
      <ToastViewportInner />
    </BaseToast.Provider>
  );
}

JavaFX

Ships in the PRIZM JavaFX library for thick-client C3 apps as PrizmToast (extends HBox). Run the gallery to see it natively.

java
import design.prizm.fx.controls.PrizmToast;

PrizmToast(Variant variant, String title, String message)
PropTypeDefaultDescription
Variantenum { DEFAULT, INFO, SUCCESS, WARNING, ERROR }DEFAULTStatus; colours the leading dot (a small dot stands in for the web's per-type icon).
PrizmToaster(StackPane host)managerBind one to a host StackPane; the bottom-right overlay that stacks toasts.
PrizmToaster.show(Variant, String title, String message[, Duration timeout]) → PrizmToastShow a toast; slides + fades in, auto-dismisses after the timeout (default 5s).
PrizmToaster.dismiss(PrizmToast) → voidDismiss early (also on the toast's ✕).

PrizmToast is one notification card (styled by .prizm-toast); PrizmToaster manages a bottom-right stack on a host StackPane (slide+fade, 5s auto-dismiss) — the instance-bound equivalent of the web `toast` singleton + ToastProvider. Mirrors components/ui/toast.tsx.