DocumentationComponentsTheme CreatorGitHub
Theme CreatorGitHubIntroduction
InstallationUsageTheming
ComponentsAccordionAction SheetAlertAlertDialogArea ChartAspectRatioAvatarBadgeBannerBar ChartBottom NavBreadcrumbButtonButtonGroupCalendarCardCarouselChartChatBubbleChatBubbleNewCheckboxChipCoachMarkCodeBlockCollapsibleColor PickerComboboxCommandContainerContextMenuDate PickerDividerDrawerDropdown MenuEmptyStateFABFieldFieldsetFile UploadFlexFormGridHoverCardIconButtonLabelLine ChartLinkMenubarMeterModalNavigation MenuNumberFieldOTP InputPaginationPickerPie ChartPopoverProgressPromptInputRadar ChartRadial ChartRadioRatingScroll AreaSearchSegmentedControlSelectShortcutSidebarSkeletonSliderCircularSliderMediaTrimmerSpacerSpinnerSplit ButtonStackStatusStepperSurfaceSwitchTableTabsTextareaTime PickerToastToggleButtonToggleGroupTokenizerToolbarTooltipTop Header DesktopTop Header Mobile
Contributing
Components

Toast

Transient floating notifications built on the Base UI Toast primitive — variants, stacking, promise flows, timer pause, swipe and full keyboard access.

Examples

Default

A basic toast with a title, description, and dismiss button. Timers pause while you hover or focus the stack, and resume when you leave.

Intents

Semantic colors and icons for success, error, warning, and info. Error toasts announce assertively (a visually-hidden role="alert" clone) and persist until dismissed; everything else announces politely.

Variants

Four materials: card (default floating panel), tinted (the intent paints the plate), inverse (the always-dark overlay plate — the snackbar), and pill (a single-line capsule that sizes to its content, ignores rounded, and drops description).

Sizes

Compact sm and standard md, plus the independent width cap.

With action

Pair a toast with an inline CTA. Action-bearing toasts default to a 10s duration (instead of 5s) so the action stays reachable — and the same operation must also exist somewhere permanent in your UI, because a toast is ephemeral by design.

Undo

The classic destructive-action follow-up: an inverse snackbar whose Undo is a regular action button (the on-color chip on the dark plate).

Promise

promise() binds a toast to an async lifecycle: a persistent loading toast with a spinner, swapped in place for the success or error content when the promise settles. The error phase persists until dismissed.

Stacking

Toasts collapse into a peeking stack; hover, focus, or F6 expands it. limit on the provider caps how many are on screen — the overflow stays mounted (data-limited, inert) and resurfaces as newer toasts leave.

Positions

Six anchors. Below the sm breakpoint every anchor renders as a full-width strip on its edge — the dominant phone presentation. Swipe-to-dismiss is derived per position: away from the anchor edge, plus toward the nearer side.

Persistence & dismissal

Errors persist by default; duration: 0 makes anything persistent; dismissible={false} removes the close button; closeLabel localizes it.

End content

endContent is a free-form trailing slot rendered beside action. When a close button is also present, the trailing row moves below the text and wraps rather than overflowing. Match the toast's rounded and button size on your own controls — the toast renders its action at xs (size="sm") or sm (size="md").

Deduplication & update

Pass a stable id to keep a repeated action from stacking duplicates (collisionBehavior: "replace" | "ignore"), or change an on-screen toast with update() — content, intent, and duration swap in place without replaying the enter animation.

Title only

A minimal toast that omits the description for short, single-line feedback — or reach for variant="pill", which is built for exactly this.

RTL

Per-toast dir (or defaultDir on the Toaster) mirrors the layout — icon, text and controls flip; closeLabel localizes the dismiss button.

Loading

Toast-shaped skeleton placeholders for queued or loading notifications. The control bars derive from the real button variants, so sizes, radii and the mobile touch floors always match.

Usage

import { Toast, ToastProvider, Toaster, useToast } from "@tessinaui/ui/toast";

Setup

Wrap your app (or layout) with ToastProvider and place Toaster where you want notifications to appear. Mount them once, at the root — the viewport is the live region, and it must exist before toasts are fired.

export default function RootLayout({ children }) {
  return (
    <ToastProvider limit={3}>
      {children}
      <Toaster position="bottom-right" />
    </ToastProvider>
  );
}

Firing a toast

function MyComponent() {
  const { toast } = useToast();

  return (
    <button onClick={() =>
      toast({
        title: "Changes saved",
        description: "Your profile has been updated successfully.",
        intent: "success",
        action: { label: "Undo", onClick: handleUndo },
      })
    }>
      Save
    </button>
  );
}

Promise lifecycles

const { promise } = useToast();

promise(saveDraft(), {
  loading: "Saving…",
  success: (draft) => ({ title: "Saved", description: draft.name }),
  error: (e) => ({ title: "Save failed", description: String(e) }),
});

Outside React

createToastManager() gives you the same API in plain modules — wire its .manager into the provider:

// toasts.ts
import { createToastManager } from "@tessinaui/ui/toast";
export const appToasts = createToastManager();

// layout.tsx
<ToastProvider toastManager={appToasts.manager}>…</ToastProvider>

// anywhere, no hook needed
appToasts.toast({ title: "Session expired", intent: "warning" });

Duration rules

CaseDefault
Plain toast5000 ms (provider timeout)
intent="error"0 — persists until dismissed
Has action10000 ms — the action stays reachable
Explicit durationalways wins (0 = persistent)

Toasts are ephemeral. Never make one the only path to information or an action — the same content must be reachable somewhere permanent.

API

Toast

The static visual card — for rendering toast anatomy inline (docs, previews, custom viewports). Fired toasts render the same anatomy automatically.

PropTypeDefaultDescription
titleReactNode—Heading line
descriptionReactNode—Supporting body text (ignored by variant="pill")
intent"none" | "error" | "warning" | "success" | "info""none"Semantic color and default icon
variant"card" | "pill" | "tinted" | "inverse""card"Visual material
size"sm" | "md""md"Compact or standard density
width"narrow" | "default" | "wide""default"Max width of the card
rounded"none" | "sm" | "md" | "lg" | "full""md"Corner radius (nested buttons follow it; full is the panel cap, the pill variant is the capsule)
iconReactNode—Overrides the default intent icon
showIconbooleantrueShow/hide the leading icon
actionToastAction—Inline CTA button (one action max)
endContentReactNode—Trailing custom content, rendered after action
dismissiblebooleantrueRender the dismiss (×) button
closeLabelstring"Dismiss notification"Accessible name of the dismiss button
onClose() => void—Renders the dismiss button and receives its click
dir"ltr" | "rtl"—Text direction
classNamestring—Extra class names

Plus every standard div attribute — style, data-* and aria-* are forwarded to the root element.

ToastAction

PropTypeDefaultDescription
labelstring—Button label
onClick() => void—Click handler (does not auto-dismiss)
variantButtonVariant"primary"Button style — "ghost" reads as an inline text action

ToastProvider

PropTypeDefaultDescription
limitnumber3Max toasts on screen; overflow collapses (data-limited, inert) and resurfaces
timeoutnumber5000Default auto-dismiss ms (0 = persistent)
toastManagerToastManager—Manager from createToastManager() for imperative use

Toaster

PropTypeDefaultDescription
positionToastPosition"bottom-right"Screen anchor for the stack
expandbooleanfalseKeep the stack expanded instead of the collapsed peek
labelstring"Notifications (F6)"Accessible name of the notifications region
defaultVariantToastVariant"card"Fallback variant
defaultSize"sm" | "md""md"Fallback size
defaultWidthToastWidth"default"Fallback width (also sizes the stack column)
defaultRoundedToastRounded"md"Fallback corner radius
defaultDir"ltr" | "rtl""ltr"Fallback direction
maxVisiblenumber—Deprecated — use limit on ToastProvider; this prop is inert
classNamestring—Extra class names on the viewport

useToast

const { toast, update, promise, dismiss, dismissAll, toasts } = useToast();
ReturnTypeDescription
toast(options: ToastOptions) => stringShows a toast; returns its id
update(id, options: Partial<ToastOptions>) => voidChanges an on-screen toast in place
promise(p, { loading, success, error }) => PromiseLoading → success/error toast bound to a promise
dismiss(id: string) => voidCloses a toast by id
dismissAll() => voidClears all toasts
toastsToastObject[]Current toast stack (Base UI shape)

ToastOptions

Everything Toast accepts visually, plus:

PropTypeDefaultDescription
idstringautoStable id for dedupe; also what dismiss()/update() take
collisionBehavior"replace" | "ignore""replace"What to do when this id is already on screen
durationnumbersee Duration rulesms before auto-dismiss; 0 = persistent
onDismiss() => void—Fired once when the toast closes, by any path
onRemove() => void—Fired after the exit transition, on unmount

ToastSkeleton

PropTypeDefaultDescription
variantToastVariant"card"Matches the toast it stands in for
size"sm" | "md""md"Density
widthToastWidth"default"Card width
roundedToastRounded"md"Corner radius
showIconbooleantrueLeading icon placeholder
showTitlebooleantrueTitle bar placeholder
linesnumber1Description line placeholders
showActionbooleanfalseAction-button placeholder
showEndContentbooleanfalseTrailing end-content placeholder
showDismissbooleantrueClose-button placeholder

Position values

ValueDescription
"top-left" / "top-center" / "top-right"Top anchors — toasts enter/exit upward, swipe up
"bottom-left" / "bottom-center" / "bottom-right"Bottom anchors (default bottom-right) — enter/exit downward, swipe down

Accessibility

The behavior layer is the Base UI Toast primitive; the contract below is pinned by the component's test suite.

Pattern. The viewport is a named role="region" live area (aria-label="Notifications (F6)", polite). Each toast renders as a non-modal dialog labelled by its title and described by its description; intent="error" toasts are priority: high — announced assertively through a visually-hidden role="alert" clone, without stealing focus. No toast ever takes focus when it appears.

Keyboard.

KeyAction
F6Move focus into the notifications viewport (expands the stack); leaving restores prior focus
Tab / Shift+TabCycle through toasts and their controls; exiting the viewport returns focus to where you were
EscClose the focused toast

Timing (WCAG 2.2.1). Auto-dismiss timers pause on hover, on focus, on window blur, and while touching a toast — and resume on leave. Errors persist until dismissed. Action-bearing toasts hold for 10s.

Swipe is a pointer convenience, never the only path — the close button, Esc and the timeout remain.

Reduced motion. Enter/exit transitions and stack movement are disabled under prefers-reduced-motion: reduce.

Your part. A toast is ephemeral: any action inside one must also exist somewhere permanent, and critical errors that demand a decision belong in a dialog, not a toast. Pass closeLabel and label when localizing.

AT status: VoiceOver smoke pending for this release. NVDA and JAWS: UNTESTED (no Windows host) — the component stays beta until passes are recorded.

Time PickerToggleButton

On this page

ExamplesDefaultIntentsVariantsSizesWith actionUndoPromiseStackingPositionsPersistence & dismissalEnd contentDeduplication & updateTitle onlyRTLLoadingUsageSetupFiring a toastPromise lifecyclesOutside ReactDuration rulesAPIToastToastActionToastProviderToasteruseToastToastOptionsToastSkeletonPosition valuesAccessibility