Toast
Overview
Transient notifications that appear in a viewport and auto-dismiss. SToastProvider renders the toast viewports and the toast imperative API creates, updates, dismisses, and inspects notifications. It supports six types, six positions, stacking/expansion, swipe-to-dismiss, promise toasts, rich color and inverted themes, and a keyboard hotkey to focus the list.
Use it for global, non-blocking feedback (saved, errors, upload progress). Prefer alert for inline callouts near content, and dialog for blocking confirmations that need a decision.
Usage
Mount one SToastProvider near your app root. If your app is already wrapped with SConfigProvider, a default SToastProvider is rendered automatically unless customToast is set to true.
Features
- ⚡ Imperative API —
toast()plustoast.success/error/warning/info/loading/custom/message/promise/dismiss - 🎨 6 types —
default/success/info/warning/error/loadingwith default icons - 📍 6 positions —
top-left/top-right/top-center/bottom-left/bottom-right/bottom-center - 🗂️ Stacking —
visibleCountslimits visible toasts per position; hover expands the stack (defaultExpanded) - 👆 Swipe to dismiss — drag left/right/up/down (configurable
swipeDirections) to remove - ⏱️ Auto-dismiss —
durationper toast/provider;0orInfinitydisables; pauses on hover and hidden-tab - 🔮 Promise toasts —
toast.promise(promise, { loading, success, error })with HTTP/Error handling - 🎛️ Actions —
action/cancelbuttons with callbacks;customfor fully custom content - ♿ Accessible —
aria-live="polite"region, focus management with focus return, and a hotkey (defaultAlt+T) to focus the list
Component family
SToastProvider(styled) — the entry provider; injectstoastVariantsand the animation stylesheetToastProvider(Aria) — thin wrapper overToasterToaster(Aria) — the state owner; subscribes toToastState, manages stack/expand/focus, renders the 6 viewportsToast(Aria) — a single toast; auto-close timer, swipe logic, height measurement, action/cancel/closetoast(imperative) — the sharedtoastcontroller (ToastStateobserver) exposed on@vean/ui
Demos
Basic
Promise
Action
Control
Appearance
Stack
API
Aria Layer
2Toaster
Props
| Prop | Type | Default | Description |
|---|---|---|---|
id | string | — | Id. |
dir | Direction | — | Reading direction of the component. |
hotkey | string[] | — | Hotkey. |
customAriaLabel | string | — | Custom aria label. |
containerAriaLabel | string | — | Container aria label. |
position | ToastPosition | — | Position. |
defaultExpanded | boolean | — | Whether default expanded. |
duration | number | — | The duration (in milliseconds) before the toast automatically closes. Set to `0` or `Infinity` to disable auto-dismissal. |
gap | number | — | Gap. |
offset | ToastOffset | 3 | The maximum number of visible toasts per position. |
visibleCounts | number | — | Visible counts. |
swipeDirections | SwipeDirection[] | — | Swipe directions. |
showIcon | boolean | — | Whether to show an icon. |
showClose | boolean | true | Whether toasts show a close button by default. A toast-level `showClose`
takes precedence over this default. |
icons | Partial<Record<ToastIconType, IconValue>> | — | Icons. |
toastProps | LiHTMLAttributes | — | Properties forwarded to the toast element. |
wrapperProps | HTMLAttributes | — | Properties forwarded to the wrapper element. |
contentProps | HTMLAttributes | — | Properties forwarded to the content element. |
titleProps | HTMLAttributes | — | Properties forwarded to the title element. |
descriptionProps | HTMLAttributes | — | Properties forwarded to the description element. |
iconProps | HTMLAttributes | — | Properties forwarded to the icon component. |
footerProps | HTMLAttributes | — | Properties forwarded to the footer element. |
actionProps | HTMLAttributes | — | Properties forwarded to the action element. |
cancelProps | HTMLAttributes | — | Properties forwarded to the cancel element. |
closeProps | HTMLAttributes | — | Properties forwarded to the close element. |
ToastProvider
Props
| Prop | Type | Default | Description |
|---|---|---|---|
size | ThemeSize | — | Visual size of the component. |
ui | ToastUi | — | Per-slot class overrides for the component. |
id | string | — | Id. |
dir | Direction | — | Reading direction of the component. |
hotkey | string[] | — | Hotkey. |
customAriaLabel | string | — | Custom aria label. |
containerAriaLabel | string | — | Container aria label. |
position | ToastPosition | — | Position. |
defaultExpanded | boolean | — | Whether default expanded. |
duration | number | — | The duration (in milliseconds) before the toast automatically closes. Set to `0` or `Infinity` to disable auto-dismissal. |
gap | number | — | Gap. |
offset | ToastOffset | 3 | The maximum number of visible toasts per position. |
visibleCounts | number | — | Visible counts. |
swipeDirections | SwipeDirection[] | — | Swipe directions. |
showIcon | boolean | — | Whether to show an icon. |
showClose | boolean | true | Whether toasts show a close button by default. A toast-level `showClose`
takes precedence over this default. |
icons | Partial<Record<ToastIconType, IconValue>> | — | Icons. |
toastProps | LiHTMLAttributes | — | Properties forwarded to the toast element. |
wrapperProps | HTMLAttributes | — | Properties forwarded to the wrapper element. |
contentProps | HTMLAttributes | — | Properties forwarded to the content element. |
titleProps | HTMLAttributes | — | Properties forwarded to the title element. |
descriptionProps | HTMLAttributes | — | Properties forwarded to the description element. |
iconProps | HTMLAttributes | — | Properties forwarded to the icon component. |
footerProps | HTMLAttributes | — | Properties forwarded to the footer element. |
actionProps | HTMLAttributes | — | Properties forwarded to the action element. |
cancelProps | HTMLAttributes | — | Properties forwarded to the cancel element. |
closeProps | HTMLAttributes | — | Properties forwarded to the close element. |
Imperative toast methods
| Method | Description |
|---|---|
toast(message, data?) | Show a default toast; returns the toast id. |
toast.success/error/warning/info/loading(message, data?) | Show a typed toast. |
toast.custom(component, data?) | Show a fully custom VNode. |
toast.promise(promise, { loading, success, error, description, finally }) | Bind a promise lifecycle to a toast. |
toast.dismiss(id?) | Dismiss one toast, or all toasts when no id is given. |
toast.getHistory() | Read all created toasts. |
toast.getToasts() | Read the currently active (non-dismissed) toasts. |
Common data options: description, position, duration, action/cancel (+ onAction/onCancel), icon, richColor, inverted, showClose, dismissible, toasterId, id, ui.
Notes
Architecture and benchmark differences
Toaster is a self-contained state owner that subscribes to a module-level ToastState observer and drives stacking/expansion, swipe, focus management and the auto-close timers, while SToastProvider only injects the recipe classes and the animation stylesheet. This is an imperative-first model like Ant Design’s message/notification, Element Plus ElMessage, Mantine notifications and Naive UI useMessage — unlike shadcn/ui which has no global toast primitive. VeanUI distinguishes itself with stacked/expandable toasts, swipe-to-dismiss, promise toasts, and a focus hotkey, matching the ergonomics of Sonner while keeping an Aria/styled split.
| Capability | VeanUI | shadcn/ui | Ant Design message | Element Plus ElMessage | Mantine notifications | Naive UI useMessage |
|---|---|---|---|---|---|---|
| Imperative API | ✅ | — | ✅ | ✅ | ✅ | ✅ |
| Types (success/error/…) | ✅ | — | ✅ | ✅ | ✅ | ✅ |
| Positions (6) | ✅ | — | ✅ | ✅ | ✅ | ✅ |
| Stack / expand | ✅ | — | — | — | ✅ | — |
| Swipe to dismiss | ✅ | — | — | — | — | — |
| Promise toasts | ✅ | — | ✅ | — | ✅ | ✅ |
| Rich color / inverted | ✅ | — | ✅ | — | — | — |
| Pause on hover / hidden tab | ✅ | — | ✅ | ✅ | ✅ | ✅ |
| Focus hotkey | ✅ | — | — | — | — | — |
— = unsupported or a different interaction model.
Cautions
- A mounted
SToastProvideris required to render toasts;SConfigProvidermounts one automatically (unlesscustomToast). durationof0orInfinitydisables auto-dismiss; the timer pauses while the toast is hovered, expanded, or the tab is hidden.visibleCounts(default3) limits visible toasts per position; older toasts stack behind and expand on hover whendefaultExpanded.- Toasts are swipe-dismissible by default; set
dismissible: falseto disable (e.g. forloading). - The viewport region is
aria-live="polite"; the default hotkeyAlt+Tfocuses the toast list. Overridehotkey/containerAriaLabelas needed.
Roadmap
No blocking gaps identified for the core toast API.
FAQ
How do I show a basic toast?
import { toast } from '@vean/ui';
toast('Changes saved');How do I show a typed toast?
toast.success('All good');
toast.error('Something went wrong');
toast.loading('Uploading…');How do I show a promise toast?
toast.promise(fetchData(), {
loading: 'Loading…',
success: data => `Loaded ${data.length} items`,
error: 'Failed to load'
});How do I change the position or duration?
Pass data options to the call (or set provider defaults):
toast('Bottom left', { position: 'bottom-left', duration: 5000 });How do I keep a toast from auto-dismissing?
Set duration: Infinity:
toast('Stays until dismissed', { duration: Infinity });How do I render custom content?
Use toast.custom with a VNode, or the custom option:
toast.custom(h(VNode));