Toast
Renderer for the headless toast queue in @plyxui/hooks. Mount the Toaster once, call toast() anywhere.
The toast queue lives in @plyxui/hooks — ToastProvider +
useToast(). @plyxui/comps ships Toaster, the renderer: a stacked
corner pile, newest on top, up to three older toasts peeking behind it.
Hovering expands the pile into a column and pauses every auto-dismiss
timer (a hidden tab pauses them too); enter/exit run through the
Presence primitive on the motion tokens.
That split is on purpose: the same queue can drive a custom snackbar, a
banner stack, or this Toaster. Apps that need a bespoke visual skip the
renderer and read from useToast() directly.
Try it live
API
import { ToastProvider, useToast } from "@plyxui/hooks";
import { Toaster } from "@plyxui/comps";
function App() {
return (
<ToastProvider>
<Routes />
<Toaster position="bottom-right" />
</ToastProvider>
);
}
function SaveButton() {
const { toast } = useToast();
return (
<Button
onClick={async () => {
await save();
toast({ title: "Saved", description: "Changes live now.", variant: "success" });
}}
>
Save
</Button>
);
}
Actions and undo
A toast can carry an action — it renders as a button, and the toast
sticks around until dismissed (an Undo the user can't reach isn't an
Undo). Explicit duration still wins if you pass one.
toast({
title: "Message archived",
action: { label: "Undo", onClick: restore },
});
Variants
default, success, warning, error. The left rail accent picks the
matching theme token. Override per variant with the accent prop.
Props
| Prop | Type | Default |
|---|---|---|
position | "top-left" | "top-right" | "top-center" | "bottom-left" | "bottom-right" | "bottom-center" | "bottom-right" |
offset | number (px from the corner) | 16 |
max | number (cap of rendered toasts; older ones animate out) | 5 |
accent | Partial<Record<ToastVariant, string>> | — |
width | number (stack width in px) | 356 |
The queue in @plyxui/hooks also grew pausable timers —
pause(id) / resume(id) / pauseAll() / resumeAll() — which the
Toaster drives on hover and tab visibility. Existing
toast({ title, description, duration }) calls work unchanged.
Native
The native Toaster lives at the same import path and supports top or
bottom positions. Same API, minus the stacking physics — hover doesn't
exist on touch, so it renders a single column with Presence enter/exit
and the same action button.