Toast
Lightweight notifications and transient feedback
Usage
Toast
Mount host once, then trigger toasts. Several at once collapse into a stack; hovering it fans the stack out and holds every countdown until the pointer leaves.
Best Practices
- Mount one host near the app root and pass
position— do not mount a host per corner. Extra hosts stand down rather than duplicating the queue, but they still cost a container and a development warning. - Use stable ids for task, save, sync, and retry notifications so repeated state updates replace the previous toast.
- Keep descriptions short; long progress, errors with recovery, or forms belong in panels, drawers, or pages.
- Clear persistent toasts when leaving the owning page or when the underlying task resolves.
API Reference
TxToastHost Props
| Prop | Type | Default | Description |
|---|---|---|---|
| position | 'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right' | 'bottom-right' | Corner (or edge centre) the stack grows from. |
| visibleToasts | number | 3 | How many toasts stay on screen. The rest wait behind, fully transparent, and move up as the front ones leave. |
| expand | boolean | false | Keep the stack fanned out instead of collapsing it when the pointer leaves. |
| gap | number | 14 | Pixels between toasts — both the expanded gap and the collapsed peek. |
| offset | number | 16 | Distance from the viewport edges. |
| swipeToDismiss | boolean | true | Let a pointer drag flick a toast off toward its own edge. |
Mount one host near the app root. A second host renders its container (so server markup still hydrates) but draws nothing, and warns in development — see Interaction Contract.
toast(options)
Import toast from @talex-touch/tuffex/utils:
toast({
id?: string
title?: string
description?: string
variant?: 'default' | 'info' | 'success' | 'warning' | 'danger'
duration?: number // default: 2600, 0 = no auto dismiss
action?: {
label: string
onClick?: (id: string) => void
dismiss?: boolean // default: true — close the toast after onClick
}
}): string
dismissToast / clearToasts
import { clearToasts, dismissToast, toast } from '@talex-touch/tuffex/utils'
const id = toast({ title: 'Queued', duration: 0 })
dismissToast(id)
clearToasts()
pauseToasts / resumeToasts / toastsPaused
TxToastHost calls these itself on pointer and focus entry, so you rarely need them. They are exported for hosts that hold the stack for their own reason — a modal opening over it, a long read.
import { pauseToasts, resumeToasts, toastsPaused } from '@talex-touch/tuffex/utils'
pauseToasts() // every countdown freezes where it is; idempotent
toastsPaused() // => true
resumeToasts() // each toast resumes from the time it had left, not from the top
Events
| Event | Payload | Description |
|---|---|---|
| - | - | No component-specific emits. The close button calls dismissToast(id) internally. |
Slots
| Slot | Props | Description |
|---|---|---|
| - | - | TxToastHost renders from the global toast store and has no slots. |
Dashboard Feedback Center
Mount TxToastHost once at the app or page root. Business actions should call toast(); persistent status notifications should use a stable id + duration: 0 so the same queue state does not stack repeatedly. In admin task centers, Toast handles transient feedback, TxTooltip explains the action, TxLoadingOverlay blocks local refreshes, and TxSpinner handles inline waiting.
Dashboard task feedback center
A screenshot-verified Toast / Tooltip / LoadingOverlay / Spinner composition.
Overview
<TxToastHost />teleports a notification region tobodywithrole="region",aria-label="Notifications", andaria-live="polite"so new toasts announce while focus is elsewhere.- Each toast includes a keyboard-focusable close button named
Dismiss notification. toast()returns the resolved id. Passing the sameidreplaces the existing toast, preventing duplicate stacked notifications for the same operation.duration > 0auto-dismisses the toast;duration: 0keeps it visible untildismissToast(id)orclearToasts()is called.- Every call raises the host z-index via the shared z-index manager so new notifications sit above the current interaction layer.
- Stacking. The newest toast is in front. Each one behind sits back by
gappixels and 5% of scale, so their top edges peek out; anything pastvisibleToastsis transparent and not clickable. Only the front toast takes pointer events while the stack is collapsed. - Hovering holds the stack. Pointer or keyboard focus entering the region fans it out to full height and calls
pauseToasts(); leaving collapses it and callsresumeToasts(), which continues each countdown from the time it had left. Collapsed, the host itself ispointer-events: none, so the empty column above the front toast stays clickable. - Swipe. Dragging a toast toward the edge it is anchored to dismisses it past 45px, or past 12px if the flick is faster than 0.32px/ms. Dragging the other way moves a fifth of the distance and springs back. A drag that starts on a button is left to the button. Set
swipeToDismiss: falseto turn this off. - One host draws the queue. Every host reads the same global store, so two would paint each toast twice in the same corner. The first to mount claims it; later hosts keep their container — server markup still hydrates cleanly — and draw nothing, warning once in development. If the owner unmounts, the next host takes over. The claim happens in
onMounted, so toasts arrive on the tick after mount rather than in the first render. - Motion. A toast arrives and leaves along the axis of its position over 0.4s;
prefers-reduced-motion: reducedrops that to a plain opacity change.
Technologies
- Accessibility note: The host is a labeled
role="region"that is also a politearia-liveregion, so a toast appearing while focus is elsewhere is announced;dangertoasts escalate torole="alert". Still use persistent visible copy or page-level status text for critical failures and long-running operations. - Single-host note: A second
TxToastHostrenders an empty container and logs a warning in development builds. Rendering nothing at all would change the server markup and break hydration, so the container stays. - Timer note: Reusing an
idreplaces the store item and first cancels that id's pending auto-dismiss timer (clearDismissTimer); the replacement toast restarts timing from its ownduration. Useduration: 0for persistent task toasts. - Verified coverage:
toast.test.tschecks id replacement, returned ids, auto-dismiss, persistent toasts, pause/resume from the remaining time, dismiss/clear helpers, host region semantics, variant classes, rendered title/description, accessible close buttons, and close-button dismissal.toast-host.test.tscovers stack order and offsets, top/bottom growth,visibleToasts, hover expansion and the hold it takes, swipe thresholds and edge resistance, action buttons, and the single-host claim. - Host source:
packages/tuffex/packages/components/src/toast/src/TxToastHost.vue. - Utility source:
packages/tuffex/packages/utils/toast.tsexportstoast,dismissToast,clearToasts,pauseToasts,resumeToasts,toastsPaused,toastStore,TxToastOptions,TxToastItem,TxToastAction, andTxToastVariant. - Export alias:
packages/tuffex/packages/components/src/toast/index.tsexports installableToastHost,TxToastHost,TxToastHostInstance,TxToastHostProps, andTxToastPosition. - Single-host registry:
packages/tuffex/packages/components/src/toast/src/host-registry.ts. - Coverage:
packages/tuffex/packages/components/src/toast/__tests__/toast.test.ts(store, timers, holds) andtoast-host.test.ts(stacking, hover, swipe, actions, single host).