Components / Feedback

ToastStack

Stack short results at the edge until you reach for them.

Install

npx shadcn@latest add https://irisui.dev/r/toast-stack.json
import { ToastStack } from "@/components/iris/toast-stack/toast-stack";
Registry item toast-stackBrings in foundationRegistry JSON

Preview

ToastStack

A queue of short, typed toasts that rise from the bottom edge, tuck behind each other, and fan out into a list on hover or focus.

When to use

  • Non-blocking results of what someone just did, when several can arrive close together: saves, exports, deletes with Undo.
  • Long-running work that should morph in place from "loading" to its result.
  • Not for a single fixed confirmation: Toast is lighter. Not for conditions that persist: use Alert.

Usage

import { ToastStack } from "@/components/iris/toast-stack/toast-stack";

// Any component rendered under ToastStackProvider can raise toasts.
function SaveButton() {
  const { toast, update } = useToastStack();
  return h(
    "button",
    {
      onClick: () => {
        const id = toast({ type: "loading", title: "Exporting 2,980 pageviews" });
        exportCsv().then(() => update(id, { type: "success", title: "Export ready" }));
      },
    },
    "Export CSV",
  );
}

h(ToastStackProvider, { duration: 5000 }, h(SaveButton), h(ToastStack, { position: "bottom-right" }));

Props

ToastStackProvider

Prop Type Default Description
children ReactNode — Required. Scope of the queue; two providers never share toasts.
duration number 5000 Base lifetime in ms. Warnings and errors stay 1.6 times longer; loading toasts wait for an update.
limit number 12 Oldest toasts beyond this count are dropped.

ToastStack (render once inside the provider)

Prop Type Default Description
position "bottom-right" | "bottom-center" | "bottom-left" "bottom-right" Corner of the window (or container).
contained boolean false Pins the stack inside the nearest positioned ancestor instead of the window.
visibleToasts number 3 How many show at once; older ones wait behind.
hotkey boolean true Alt+T moves focus into the stack.
label string "Notifications" Accessible name of the region.
className string — Extra class.

useToastStack() returns { toast, update, dismiss, count } and must be called inside a ToastStackProvider; count is how many toasts are queued.

Toast options passed to toast(): { id?, type?: "success" \| "info" \| "warning" \| "error" \| "loading", title, description?, action?: { label, onClick(id) }, duration? }. update(id, patch) morphs a toast in place and restarts its timer; dismiss(id?) closes one or all.

Notes

  • Calling useToastStack() outside a ToastStackProvider throws. Each provider scopes its own queue.
  • Reusing an id in toast() updates that toast in place instead of stacking a new one.
  • The region is aria-live="polite". Timers pause while the stack is hovered, focused, being dragged, or the tab is hidden. Swipe right to dismiss.
  • Reduced motion replaces the stacking springs with fades.
  • Reads --surface, --hover, --line, --line-strong, --ink, --ink-2, --ink-3, --shadow-raised, --shadow-floating, and the tone tokens --green, --accent, --orange, --red.