Designer view

Toast

A transient floating notification anchored to a corner of the viewport, auto-dismissing after a short visible duration. Distinct from Alert (inline, persistent) by its ephemerality and positioning; distinct from Modal (blocking) by its non-modal contract. Used for success confirmations after asynchronous actions, transient status messages, undoable operations, and short notifications that do not require explicit acknowledgement.

When to use

Use

For transient confirmations after asynchronous actions ("Saved", "Copied"), undoable operations ("Item deleted · Undo"), and short non-essential status updates the user can safely miss. Toast is non-blocking and auto-dismisses; users do not need to acknowledge.

Avoid

For critical errors requiring user action — that is `Alert` (inline persistent) or `Modal` (blocking). For long informational content — that is `Alert` or page prose. For on-demand description — that is `Tooltip`. For page-wide persistent notices — that is `Banner`.

Versus related

  • alert

    `Alert` is inline and persistent; `Toast` is floating and auto-dismissed. Alert is for situations the user may need to revisit or act on; Toast is for transient signals the user can miss without consequence.

  • modal

    `Modal[variant=alertdialog]` is blocking and demands explicit response; `Toast` is non-blocking and ephemeral. They occupy opposite ends of the notification-urgency spectrum.

  • banner

    `Banner` is page-wide, persistent, and informational (e.g. a maintenance notice at the top of every page); `Toast` is corner-anchored, ephemeral, and action-triggered. Banner is system-level; Toast is action-level.

  • tooltip

    `Tooltip` is hover/focus-revealed descriptive text; `Toast` is system-pushed notification. Tooltip is pulled by the user; Toast is pushed by the system.

Highlight
Fig 1.1 · Toast · Designer view
Designer

Figma anatomy

Slot Figma type Hint
viewport frame Fixed-position frame at one viewport corner; padding from safe-area-inset
container frame Auto-layout horizontal frame; severity drives accent treatment
icon instance Icon component instance; glyph swap bound to severity Variant
title text Heading text style; bound to a component property
body text Body text style; bound to a component property
action instance Button instance; visibility bound to hasAction property
dismiss-button instance Icon button instance; visibility bound to dismissible property
Designer

Token usage per slot

viewport
spacing
  • paddingspacing.compact
  • gapspacing.tight
container
spacing
  • paddingspacing.compact
  • gapspacing.compact
radius
  • cornerradius.md
color
  • backgroundcolor.surface.raised
  • bordercolor.border.subtle
elevation
  • shadowelevation.lg
icon
color
  • foregroundcolor.text.accent
title
color
  • foregroundcolor.text.primary
typography
  • sizetext.sm
  • weightweight.semibold
body
color
  • foregroundcolor.text.primary
typography
  • sizetext.sm
  • lineHeightleading.snug
action
spacing
  • paddingspacing.tight
radius
  • cornerradius.sm
color
  • foregroundcolor.text.accent
  • ringcolor.border.focus
dismiss-button
spacing
  • paddingspacing.tight
radius
  • cornerradius.sm
color
  • foregroundcolor.text.muted
  • ringcolor.border.focus
Both

Figma ↔ Code property map

FigmaTypeCodeNotes
SeverityVariantseverityMaps info / success / warning / error. Drives role (status vs alert) plus visual treatment plus icon glyph.
PositionVariantpositionSix options covering corners and centres. Set on the viewport, not per-toast.
DismissibleBooleandismissibleToggles the dismiss-button slot visibility plus Escape handling.
Has IconBooleanhasIcon
Has TitleBooleanhasTitle
Has ActionBooleanhasActionToggles the action slot. Single action per toast by canon.
TitleTexttitle
BodyTextbody
Action LabelTextactionLabel
IconInstance SwapiconSeverity icon glyph; designers may swap for domain-specific icons.
Designer

Motion

TransitionDuration token
openmotion.duration.fast
closemotion.duration.fast
swipeDismissmotion.duration.fast
Easing
motion.easing.decelerate
Reduced motion
Instant (jump cut)
Designer

Responsive behaviour

BreakpointChange
breakpoint.smAt and below, the toast viewport spans the inline-size of the screen and anchors to the bottom regardless of the authored `position` (top-anchored toasts on mobile cover the address bar or status area). Toast container fills the inline-size minus safe-area padding. Stack depth canonical maximum drops from 3 to 2 to preserve screen real estate.
breakpoint.mdAbove this width, the viewport renders at the authored position with toasts sized to their max-inline-size. Stack depth canonical maximum is 3.
Both

Internationalisation

RTL · mirroring

Position values are logical: `start` and `end` follow inline direction (top-end is visual top-right in LTR, top-left in RTL). Dismiss button moves with the inline-end logical anchor. Action button order is unchanged within the toast (single action by canon). Severity icons are direction-neutral. Slide-in animations use logical transform directions — toasts entering from inline-end slide from visual right in LTR, visual left in RTL.

Text expansion

Title and body grow with translation. Max-inline-size on the container constrains horizontal growth; long-text languages wrap to additional lines. Auto-dismiss duration may need to extend in long-text locales — the canonical formula is "2 seconds + 1 second per ~50 characters" rather than a fixed duration. Action button label follows Button's expansion rules; single-action toasts do not have multi-button wrap issues.

Both

Variants, properties, states

Variants

Structurally different versions of the component.

infosuccesswarningerror

Properties

The same component, parameterised.

PropertyType
positiontop-start | top-end | bottom-start | bottom-end | top-center | bottom-center
dismissibleboolean
hasActionboolean
hasIconboolean

States

Browser/user-driven (interactive) vs. app-driven (data).

KindStates
interactive
hoverfocus-visible
data
openingopenpausedclosingclosed
Both

State transitions

FromToTrigger
closedopeningConsumer triggers the toast (typically after an async operation completes). The toast is mounted in the viewport region; the auto-dismiss timer is initialised but not yet started.
openingopenThe slide-in animation completes (or, under prefers-reduced-motion reduce, immediately). The auto-dismiss timer starts; the live region announces the toast content.
openpausedUser hovers anywhere inside the toast viewport region OR focus moves into the toast region. The auto-dismiss timer pauses for all toasts in the viewport, not just the hovered one.
pausedopenUser leaves the viewport region (pointer and focus both out). The auto-dismiss timer resumes from where it paused (NOT restarted from full duration — the elapsed time before pause counts).
openclosingThe auto-dismiss timer expires; or the user presses Escape with focus inside the toast region; or the user activates the dismiss button or invokes the action; or the consumer programmatically closes the toast.
closingclosedThe slide-out animation completes (or immediately under reduced motion). The toast is removed from the viewport and from the live region. Subsequent toasts in the stack reflow.
Both

Figma↔Code mismatches

  1. 01
    Figma

    A toast drawn next to the trigger that surfaced it

    Code

    A toast rendered in a fixed-position viewport region at a corner of the screen

    Consequence

    Designers may anchor toasts to specific UI elements in mocks (next to the save button, below the form). Implementations following the Figma file create per-trigger floating surfaces that compete with each other and miss the stacking, the auto-dismiss, and the live-region semantics.

    Correct

    Toast lives in a single viewport region per page (or per window scope), not anchored to triggers. The position property selects which corner; the viewport region handles stacking and live-region semantics. Document the singleton viewport contract explicitly.

  2. 02
    Figma

    Toast auto-dismiss drawn as a single visual state with no progress indicator

    Code

    An auto-dismiss timer driving slide-out at a configurable duration

    Consequence

    Designers may not realise the toast disappears automatically; developers ship without a progress affordance and users feel surprised when the toast vanishes mid-read. Worse, implementations may default to too-short or too-long durations.

    Correct

    Document auto-dismiss as a canonical behaviour with a configurable duration property (or a fixed canonical default such as 5 seconds). An optional progress indicator slot may visualise remaining time. Hover-pause is canonical to protect users who are reading.

  3. 03
    Figma

    Multiple toast variants for stacking visualisation

    Code

    A single toast component plus a viewport region that handles stacking

    Consequence

    Designers create "single toast", "two toasts", "three toasts" variants in the design file. Developers ship one toast plus stacking logic; the design file's three-toast variant is decorative, not real, and the production stack behaves differently.

    Correct

    Stacking is a viewport-region concern, not a toast variant. Document the canonical stack-depth maximum and the stacking animation in the viewport's anatomy slot. The toast itself is a single component; the viewport orchestrates.

  4. 04
    Figma

    Toast action drawn as link-styled inline text inside body

    Code

    Toast action as a Button in the action slot

    Consequence

    Designers compose body text with inline link "Undo"; the embedded interaction is either a real anchor (wrong semantic — Undo does not navigate) or a span with click handler (no semantic at all). Keyboard reachability and announcement contracts both suffer.

    Correct

    Single action lives in the dedicated action slot as a Button element (typically with `variant: tertiary` or `ghost`). The body describes the situation; the action is separately reachable by Tab.

Designer

Common mistakes

#toast-no-pause-on-hover

Auto-dismiss continues while the user reads

Problem

The toast slides in, the user starts reading, the timer fires, the toast slides out. Users with motor impairments, cognitive impairments, or simply slow reading speed cannot reliably consume the message. WCAG 2.2.1 (Timing Adjustable) is failed.

Fix

Pause the auto-dismiss timer on pointer-enter and focus-into the viewport region. Resume on pointer-leave AND focus-out (both must be true). Some implementations pause on individual toast hover; canonical pauses on viewport-level hover so users can move between adjacent toasts.

#toast-stack-overflow

Toast stack grows unbounded

Problem

Multiple toasts fire in rapid succession; the stack grows to 5, 10, 20 toasts. SR users hear a torrent of announcements; pointer users see the screen filled with notifications. The viewport overflows.

Fix

Cap the canonical stack depth at 3 visible toasts. Beyond that, queue new toasts and only render them when an existing toast dismisses. Document the threshold in performance. The queue is invisible — users do not know how many toasts are pending.

#toast-essential-info

Critical errors delivered as toast

Problem

A network failure or data-loss warning is shown as an auto-dismissing toast. The user misses it (auto-dismiss); the underlying problem persists; data is lost without recourse.

Fix

Critical errors that require user action are Alert (inline persistent) or Modal (blocking). Toast is reserved for transient confirmations and non-essential updates the user can miss without consequence. Document the canonical severity-to-component map: success and info → toast or alert; warning → alert; error requiring action → alert or modal.

#toast-aria-live-assertive-for-info

Info-severity toast uses assertive live region

Problem

Toasts carry `role="alert"` (assertive) regardless of severity. SR users are interrupted for every "Saved" / "Copied to clipboard" confirmation; the assertive flood makes them disable notifications entirely.

Fix

Match severity to live-region politeness: info / success → `role="status"` (polite), error → `role="alert"` (assertive), warning is canonical-default polite (re-evaluate per use case). Document the mapping; reserve assertive for content that genuinely interrupts.

#toast-no-keyboard-dismiss

Escape does not dismiss the focused toast

Problem

Keyboard users tabbing into the toast region cannot exit via Escape — the only way to dismiss is to tab to the dismiss button and activate, or wait for auto-dismiss. The keyboard contract feels broken compared to other light-dismiss patterns (Popover, Tooltip).

Fix

Bind Escape on the viewport region: when focus is inside the toast region, Escape dismisses the focused toast (or the most recent toast if none is focused). Document the keyboard contract in a11yAcceptance.

Accessibility hints
Slot Accessibility hint
viewport Apply `role="region"` with `aria-label="Notifications"` so SR users can navigate to the toast region by landmark. The region itself is not a live region — individual toasts inside carry their own polite or assertive live-region roles depending on severity. Hover anywhere inside the viewport pauses the auto-dismiss timers of all visible toasts.
container Apply `role="status"` (polite, default) for info and success severities, or `role="alert"` (assertive) for error severities. Warning sits on the boundary — canonical default is polite to avoid interrupting the user's work. Both roles imply implicit live regions.
icon Decorative — `aria-hidden="true"`. Severity is communicated through the `role` and the visible body text, never through the icon glyph alone.
title Plain `<strong>` or styled `<p>`; heading semantics not required for transient toasts. SR announces the title followed by the body in DOM order.
body Plain prose. Capped at one to two sentences by canon. Anything longer should be an Alert.
action Real button with accessible name. Receives focus when the user tabs into the toast region (after the dismiss button); pressing Tab exits the region. Activation triggers the consumer-provided handler and typically dismisses the toast as a side effect.
dismiss-button Provide an accessible name ("Dismiss" or "Dismiss notification"). Activation removes the toast from the viewport and from the live region. Escape key (when toast region has focus) does the same.