Trivela UI

Toast

A floating notification. Wrap the app in ToastProvider, then call toast() from anywhere.

The panel does not float on its own — ToastProvider is what makes it float. The provider owns the queue and renders a fixed strip into document.body through a portal. Rendering <Toast> directly puts it inline, in the flow, like any other div — still useful for a message that belongs on the page.

A toast carries role="status", not role="alert": it reports something that already happened and should wait for a natural pause rather than cut a screen reader off. Inside the provider the strip is the live region, so individual toasts drop the role to avoid nesting one inside another. Hovering or focusing a toast stops its timer — an auto-dismissing message that vanishes mid-read fails WCAG 2.2.1.

Try a valid address for success, or one containing “fail” for the error.

Usage

toast-demo.tsx
import { ToastProvider, useToast } from 'trivela-ui';

// Wrap the app once.
export function App({ children }) {
  return <ToastProvider position="bottom-right">{children}</ToastProvider>;
}

// Then float a toast from anywhere below.
export function SubscribeForm() {
  const { toast } = useToast();

  async function handleSubmit(event) {
    event.preventDefault();
    try {
      await subscribe();
      toast({ color: 'success', icon: true, title: 'Subscribed' });
    } catch {
      toast({ color: 'danger', icon: true, title: 'Could not subscribe' });
    }
  }

  return <form onSubmit={handleSubmit}></form>;
}

Examples

On submit

The usual case: float a result after a request settles. Submit a valid address for success, or one containing “fail” for the error — the toast appears bottom-right, over the page.

Try a valid address for success, or one containing “fail” for the error.

Inline panel

Rendered directly, Toast is an inline panel — no floating, no timer. Each color carries its own icon, so the meaning does not rest on color alone.

Success

Your changes have been saved.

Syncing

Your workspace is being updated.

Low storage

You are using 92% of your quota.

Upload failed

The file was larger than 25 MB.

Dismissible

Pass onDismiss to get the close button. Toast does not hide itself — it reports the intent and you own the state.

Success

Your changes have been saved.

Syncing

Your workspace is being updated.

Low storage

You are using 92% of your quota.

Upload failed

The file was larger than 25 MB.

Provider options

position anchors the strip to any corner or edge. duration is the default lifetime, and max caps the queue so a burst of requests cannot bury the screen — the oldest drops off.

position: top-left · top-center · top-right · bottom-left · bottom-center · bottom-right

duration: milliseconds, default 5000. 0 or Infinity keeps the toast up until dismissed.

max: default 4. The strip above is live — submit the form a few times quickly and watch the oldest fall off.

Custom icon

Pass any node instead of true — a lucide icon, or your own SVG.

Deployed

Build 1a2b3c is live.

Variants

Four style variants, matching the rest of the system.

solid

A short description appears here.

outline

A short description appears here.

subtle

A short description appears here.

ghost

A short description appears here.

API Reference

PropTypeDefaultDescription
useToast().toast(options: ToastOptions) => stringFloats a toast and returns its id. Options: title, description, color, variant, icon, duration, dismissLabel.
useToast().dismiss(id: string) => voidRemoves one toast by the id that toast() returned.
useToast().dismissAll() => voidEmpties the queue.
ToastProvider position'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right''bottom-right'Where the fixed strip anchors.
ToastProvider durationnumber5000Default lifetime in ms. 0 or Infinity keeps toasts up. Hover or focus pauses it.
ToastProvider maxnumber4Queue cap. The oldest toast drops off beyond this.
variant'solid' | 'ghost' | 'outline' | 'subtle''solid'Style variant for the component.
color'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info' | 'neutral''success'Color scale used by the component.
iconboolean | ReactNodetrue renders the icon matching color; pass a node for your own. Omit for no icon.
titleReactNodeHeading above the description.
onDismiss() => voidRenders the close button and fires on click. Toast does not hide itself.
dismissLabelstring'Dismiss'Accessible name for the close button.
classNamestringMerged with the generated classes via cn().
...propsHTMLAttributes<HTMLDivElement>Forwarded to the root. role defaults to 'status' and can be raised to 'alert'.