Toast Stack
NewA provider and useToast hook. Toasts stack into a deck, fan out on hover, and swipe away to dismiss.
motionlucide-reactutils@soultel/use-reduced-motion-safe
hover the stack, swipe to dismiss
Installation
$ pnpm dlx shadcn@latest add @soultel/toast-stackNo namespace set up? npx shadcn@latest add https://asafefe.dev/r/toast-stack.json works too.
Manual installation
- 1. Install the dependencies.
terminal1 lines npm install motion lucide-react - 2. Copy the source from the Code tab into components/toast-stack.tsx.
Usage
// layout.tsx
import { ToastProvider } from "@/components/toast-stack"
export default function Layout({ children }: { children: React.ReactNode }) {
return <ToastProvider position="bottom-right">{children}</ToastProvider>
}
// anywhere inside
import { useToast } from "@/components/toast-stack"
export function SaveButton() {
const { toast } = useToast()
return <button onClick={() => toast.success("Changes saved", { description: "Your profile is up to date." })}>Save</button>
}Props
| Prop | Type | Default | Description |
|---|---|---|---|
| position | "bottom-right" | "bottom-center" | "top-right" | ... | "bottom-right" | Corner of the viewport the stack sits in. |
| duration | number | 4000 | Default time on screen in ms. Timers pause on hover, focus, and hidden tabs. |
| visibleToasts | number | 3 | Toasts shown in the deck. The rest wait behind. |
| gap | number | 10 | Space between expanded toasts in px. |
| className | string | - | Viewport classes. "absolute" keeps the stack inside a relative parent. |
| toast(title, options) | => id | - | options: description, variant, duration, action, id. Also toast.success, toast.error, toast.info. |
| dismiss(id?) | void | - | Dismiss one toast, or all of them without an id. |
