Toast

Lightweight notifications and transient feedback

VerifiedSince 0.3.4

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.

Loading demo...

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

PropTypeDefaultDescription
position'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right''bottom-right'Corner (or edge centre) the stack grows from.
visibleToastsnumber3How many toasts stay on screen. The rest wait behind, fully transparent, and move up as the front ones leave.
expandbooleanfalseKeep the stack fanned out instead of collapsing it when the pointer leaves.
gapnumber14Pixels between toasts — both the expanded gap and the collapsed peek.
offsetnumber16Distance from the viewport edges.
swipeToDismissbooleantrueLet 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:

EXAMPLE.TS
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

EXAMPLE.TS
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.

EXAMPLE.TS
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

EventPayloadDescription
--No component-specific emits. The close button calls dismissToast(id) internally.

Slots

SlotPropsDescription
--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.

Loading demo...

Overview

  • <TxToastHost /> teleports a notification region to body with role="region", aria-label="Notifications", and aria-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 same id replaces the existing toast, preventing duplicate stacked notifications for the same operation.
  • duration > 0 auto-dismisses the toast; duration: 0 keeps it visible until dismissToast(id) or clearToasts() 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 gap pixels and 5% of scale, so their top edges peek out; anything past visibleToasts is 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 calls resumeToasts(), which continues each countdown from the time it had left. Collapsed, the host itself is pointer-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: false to 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: reduce drops that to a plain opacity change.

Technologies

  • Accessibility note: The host is a labeled role="region" that is also a polite aria-live region, so a toast appearing while focus is elsewhere is announced; danger toasts escalate to role="alert". Still use persistent visible copy or page-level status text for critical failures and long-running operations.
  • Single-host note: A second TxToastHost renders 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 id replaces the store item and first cancels that id's pending auto-dismiss timer (clearDismissTimer); the replacement toast restarts timing from its own duration. Use duration: 0 for persistent task toasts.
  • Verified coverage: toast.test.ts checks 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.ts covers 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.ts exports toast, dismissToast, clearToasts, pauseToasts, resumeToasts, toastsPaused, toastStore, TxToastOptions, TxToastItem, TxToastAction, and TxToastVariant.
  • Export alias: packages/tuffex/packages/components/src/toast/index.ts exports installable ToastHost, TxToastHost, TxToastHostInstance, TxToastHostProps, and TxToastPosition.
  • 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) and toast-host.test.ts (stacking, hover, swipe, actions, single host).
查看源码
packages/tuffex/packages/components/src/toast/index.ts