Motion UIComponentsComponent

Toast stack

Toasts that fan into a scaled pile at the bottom of the screen and settle on a shared spring.

npx shadcn@latest add @motion/toast-stack

API reference

Components

<Toast />

One animated card in the stack. Reads its index and the shared geometry from the ToastStack context and renders the motion.div that carries the fan-out choreography: the index-derived rise/scale/fade, the settle spring with a per-step stagger, the enter/exit throws, and the z-order. Toasts beyond maxVisible are kept mounted (so the stack keeps its depth) but faded out, aria-hidden, and pointer-inert.

children?

ReactNode

The toast's content - typically a NotificationCard carrying the icon, title, body and a dismiss button. The Toast never styles the face, only moves it.

className?

string

Merged onto the animated card element. Positioning (absolute bottom / full width / stacking transform) is owned by the mechanic; use this only for extra per-toast styling.

<ToastStack />

The stack viewport. Paints the fixed bottom-centred well, wraps the toasts in an AnimatePresence so enter and exit are layout-animated, and computes the shared geometry + reduced-motion mode every Toast reads. The well is pointer-events-none so the gaps around the toasts never swallow clicks; each visible toast re-enables pointer events for itself. Render Toast children inside; the stack positions them, they supply their own content.

children?

ReactNode

The Toast children, newest first (map useToastStack().toasts in order). More may be passed than are shown; the stack keeps maxVisible + 2 mounted (the extra two are the hidden exit tail) and drops the rest.

maxVisible?

number = 4

How many toasts stay fully visible before the rest hide behind them. Defaults to 4.

stackOffsetY?

number = 10

Vertical push, in px, applied per step back in the stack. Defaults to 10.

stackScale?

number = 0.06

Scale shed per step back in the stack (0.06 = 6% smaller each). Defaults to 0.06.

stackOpacity?

number = 0.2

Opacity shed per step back in the stack. Defaults to 0.2.

className?

string

Merged onto the fixed viewport element - reposition the well (e.g. top instead of bottom) or widen it here.

Hooks

useToastStack

The headless toast queue. Owns nothing visual: it hands back the ordered id list plus add/dismiss so a consumer wires their own trigger and their own event source, then renders the ids as Toast children of a ToastStack. Newest toasts are prepended, so the queue is naturally front-to-back.

useToastStack(): UseToastStackResult

Returns

toasts

ToastItem[]

The live queue of toast ids, newest first - map it into Toast children inside a ToastStack.

add

() => ToastItem

Push a new toast onto the front of the queue, returning its id. Wire this to your own trigger.

dismiss

(id: ToastItem) => void

Remove the toast with id (typically from its dismiss button).

useToast

Reports whether the enclosing Toast is inside the visible window. Read it from a control the consumer drops into a toast (a dismiss button) so the control can set tabIndex={isVisible ? undefined : -1} and stay out of the tab order while its toast is hidden behind the stack. Returns isVisible: true outside a Toast, so a control reused elsewhere never breaks.

useToast(): ToastVisibility

Related examples