Toaster
Toast notifications: brief, temporary messages anchored to the edge of the screen. Auto-dismiss on a timer; pause on hover; manually dismissable. Built on vue-sonner.
ts
const { toast } = useToast()
toast.success({ title: 'Saved', description: 'Your changes are live.' })
toast.error({ title: 'Sync failed', description: 'Something went wrong.' })Toasts are non-blocking — they confirm or report something happened without interrupting the workflow. If the user has to make a decision, that's a Modal. If the message needs to stay visible until resolved, that's a Banner.
useToast() is a global singleton (created with @vueuse/core's createGlobalState) — calling it anywhere returns the same toast function.
When to fire a toast
- System feedback — confirm a background action completed (file saved, export ready, settings updated)
- Async operations — notify when a long-running task finishes without forcing the user to watch it
- Transient alerts — surface info that doesn't require any action
When not to fire a toast
- Critical errors that need a decision — use a
Modalor inline error - Persistent information the user needs to refer back to — toasts auto-dismiss; put it in the UI instead
- Stacking many notifications — keep simultaneous toasts to ~3. If many fire at once (bulk operations), summarise into one toast.
Writing toast copy
- Keep it short — aim for ~10 words. "3 buildings updated." beats "The bulk update operation has completed and 3 buildings were updated successfully."
- Confirm what happened, in past tense. "Report exported." not "Exporting…".
- Sentence case, never all caps. No alarmist language — that's what a
Modalis for. - For errors, add brief remediation in the description. "Export failed." → "Check your connection and try again."
Variant durations
| Variant | Duration | Use for |
|---|---|---|
success | Auto-dismiss (3 s) | Confirmation of an action that completed |
info / default | Auto-dismiss (4 s) | Neutral feedback, async progress |
warning | Auto-dismiss (5 s) | Non-blocking concern the user should notice |
error | Persistent | Failure the user should read and dismiss |
missing | Persistent | Required data is absent |
Errors and missing-info stay until dismissed — the user shouldn't miss them while reaching for the mouse.
Setup
Mount <Toaster /> once at the app root.
html
<Toaster />ts
import { Toaster } from '@scaler-tech/aurora/toaster'Fire a toast
ts
import { useToast } from '@scaler-tech/aurora/toaster'
const { toast } = useToast()
toast({
variant: 'success',
title: 'Saved',
description: 'Your changes are live.',
})
// or, equivalently, via the variant shorthand:
toast.success({
title: 'Saved',
description: 'Your changes are live.',
})toast.success, toast.error, toast.warning, toast.info, and toast.missing are convenience methods that pre-fill variant. Each accepts either a string (used as description) or an options object.
Variants
ts
toast({ variant: 'success', title: 'Saved', description: 'Your changes are live.' })
toast({ variant: 'error', title: 'Sync failed', description: 'Something went wrong.' })
toast({ variant: 'warning', title: 'Warning', description: 'Please review your input.' })
toast({ variant: 'info', title: 'Heads up', description: 'A new feature is available.' })
toast({ variant: 'missing', title: 'Missing data', description: 'Some required info is missing.' })Persistent toast (duration: 0)
Pass duration: 0 for a toast that doesn't auto-dismiss. The user closes it via the close button.
ts
toast({
variant: 'warning',
title: 'Persistent toast',
description: 'This toast will not auto-dismiss. Click the X to close.',
duration: 0,
})Hover to pause
Auto-dismiss timers pause while the user hovers over a toast. Resume on mouseleave. Built into vue-sonner — no config needed.
Re-fire the same toast (replace by id)
Pass an id. Calling again with the same id dismisses the previous toast (with its close animation), then shows the new one. Toasts without an id always stack.
Click the first button repeatedly — each new toast replaces the previous. Click the second button repeatedly — they stack.
ts
toast({
id: 'toast-with-id',
title: 'Toast with id',
description: 'This toast has an identifier and will replace the old one',
})
toast({
title: 'Regular toast',
description: 'This toast has no identifier and will stack up',
})Useful for status updates where the same conceptual message ("Calculating…", "Synced") fires from multiple code paths.
Action button
Add a trailing action button. The toast stays open until the user clicks the action or the close button (or until duration elapses).
ts
toast.info({
title: 'Saved',
description: 'Used data has been updated',
duration: 5000,
closeButton: false,
action: {
label: 'Undo',
onClick: () => { /* … */ },
},
})Without rich colors
By default, toasts use a tinted background that matches the variant. Pass richColors: false for a neutral white background with only the variant border + icon.
ts
toast({
variant: 'success',
title: 'Subtle toast',
description: 'No tinted background',
richColors: false,
})Burst behavior
When toasts fire in rapid succession (within 300ms of each other), useToast adds a 50ms delay between consecutive toasts so they cascade in instead of stacking on top of each other. Single toasts fire with no delay.
ts
for (let i = 1; i <= 5; i++) {
toast({ variant: 'success', title: `Toast ${i}`, description: `Number ${i}` })
}Toaster — Props
| Prop | Type | Default | Description |
|---|---|---|---|
position | 'top-left' | 'top-right' | 'top-center' | 'bottom-left' | 'bottom-right' | 'bottom-center' | 'top-right' | Anchor for the toast stack. |
offset | { top?: number; right?: number; bottom?: number; left?: number } | — | Pixel offsets from the chosen anchor. |
The component renders up to 5 visible toasts at once with an 8px gap between them.
toast options
| Field | Type | Default | Description |
|---|---|---|---|
variant | 'success' | 'error' | 'warning' | 'info' | 'missing' | 'info' | Semantic color and matching icon. |
title | string | VNode | — | Bold first line. |
description | string | — | Body text below the title. |
duration | number | 3000 | Ms before auto-dismiss. 0 keeps the toast until manually dismissed. |
richColors | boolean | true | Tinted background + matching variant border. false = neutral white background. |
closeButton | boolean | true | Show the trailing close (X) button. |
action | { label: string; onClick: () => void } | — | Trailing action button. |
id | string | number | auto | Stable id — re-using one updates the existing toast in place. |
Other vue-sonner ExternalToast options (onDismiss, onAutoClose, cancel, position, etc.) are forwarded through.
Variant map
| Variant | Icon |
|---|---|
success | check-circle (success-core color) |
error | exclamation-circle (error-core) |
warning | minus-circle (warning-core) |
missing | exclamation-circle (missing-core) |
info | information-circle (cta) |