Dashral Pro is on the wayGet 30% off at launch

Dashral

Toast

Toast with motion: toasts spring in and the stack glides to make room, a changing toast pops its icon over, and a swipe sends one away.

$ pnpm dlx shadcn@latest add https://dashral.com/r/motion-toast.json

Installation

$ pnpm dlx shadcn@latest add https://dashral.com/r/motion-toast.json

Adds components/dashral/motion/toast.tsx, the Toast it builds on (in components/dashral/), motion and the motion files every motion component shares. With the registry in your components.json:

$ pnpm dlx shadcn@latest add @dashral/motion-toast

Usage

The same as Toast, imported from components/dashral/motion/: swap the import and it moves.

example.tsx
// Once, near the root of your app:
import { Toaster } from "@/components/dashral/motion/toast"

<Toaster position="bottom-right" />

// Anywhere:
import { toast } from "@/components/dashral/motion/toast"

toast.success("Changes saved")
toast("Archived", { action: { label: "Undo", onClick: restore } })

Examples

Every kind

Default, success, error with an action, and a promise that goes from Publishing… to Published in one toast. Swipe one sideways to close it.

Archive with undo

Each archived row folds away and a toast springs in with Undo, which puts the row back in its place; archive a few and they stack.

Maya Chen

Q4 planning notes

Billing

Your invoice for October

Leo Park

Design review moved to 3 pm

Support

Ticket #2291 was resolved

Compared with Default

Default

Toasts slide in from the corner and stack.

Motion

Toasts fold into a stack that spreads on hover; a new one springs in and pushes it back; a toast that changes (loading to done) pops its icon over and crosses its words; a swipe sideways sends it off.

How the two editions differ in general, and which to use where: Motion.

API reference

Its own API, in place of Toast's:

Toaster

Mount it once near the root of your app.

PropTypeDefault
position"top-left" | "top-center" | "top-right" | "bottom-left" | "bottom-center" | "bottom-right"

Where the toasts gather.

"bottom-right"
visibleToastsnumber

How many show at once; older ones wait their turn.

3
durationnumber

How long a toast stays, in milliseconds, unless it says otherwise.

4000
classNamestring

The stack's classes.

—

toast(message, options)

Shows a toast and returns its id. Also toast.success, .info, .warning, .error and .loading (with the type's icon), toast.promise(promise, { loading, success, error }) and toast.dismiss(id?).

PropTypeDefault
descriptionReactNode

A second line under the message.

—
action{ label, onClick }

A button in the toast; clicking it also closes the toast.

—
durationnumber

How long it stays, in milliseconds; Infinity keeps it until it's closed. Loading toasts stay by default.

Toaster's
idstring | number

An existing toast's id, to change it in place (Saving… to Saved).

—
iconReactNode

In place of the type's icon.

—
onDismiss() => void

Called when it closes, by its timer, a swipe or toast.dismiss().

—

Its own toast() and <Toaster />, without sonner: the calls are the same as the default edition's.

Motion

  • Toasts fold into a stack: the newest in front, the two before it peeking out behind (10px each), smaller and fainter, cut to the front one's height. Hover or tap and the stack spreads into a list on a spring, holding the timers; leave and it folds back.
  • A new toast springs in from its edge (--duration-standard, a hint of overshoot) and the toasts already there glide aside to make room; a closing one shrinks and fades (--duration-fast).
  • A toast that changes (toast.promise, or the same id again) pops its new icon over the old and crosses its words over, and the toasts around it glide to its new size.
  • Drag one sideways and it follows; let go past 80px, or flick it, and it leaves that way; short of it, it springs back.
  • Hovering the stack holds the timers. With reduced motion toasts only fade and don't drag.