ui-006

Toast Notifications

£10 or the whole Vault, £99

Toast notifications for web apps: five types, undo actions, a pause-on-hover countdown, swipe to dismiss and a promise helper for loading states.

intermediate
7 more details
micro-interactionstaggertimed-streamprogress-bardragstate-transitionkeyboard-navigation

This element reads better at your own screen size than in the frame below:

Updated

About this component

A toast queue with the parts real products need. Five types (success, error, warning, info and a neutral default) each carry their own icon and accent, and each is announced at the right urgency: errors take role=alert and aria-live=assertive, everything else waits its turn politely. A toast can carry one action button, the Undo pattern, and the call that spawned it gets a promise back telling it whether the toast timed out, was dismissed, was thrown away or had its action pressed.

Read the full effect overview

The countdown is a paused-and-resumed GSAP tween rather than a setTimeout, so hovering or tabbing into the stack holds the progress bar exactly where it is and leaving resumes it from there. Toasts can be thrown away with a pointer or a finger: past a distance or velocity threshold the card flies out, otherwise it springs back on an elastic ease and keeps its remaining time. Past the visible limit the older toasts tuck behind a "+N more" chip that expands on hover, on focus or on a tap, and toasts nobody can see stop counting down. toast.promise() morphs a single card through loading, success and error instead of spawning three. Light and dark themes, defined entirely in CSS custom properties.

Toast Notifications - UI component preview

What's included

10 items
  • Five types with their own icon and accent, all set from custom properties
  • Politeness follows the type: errors are role=alert and assertive, the rest polite
  • Optional action button (the Undo pattern) with a promise that tells the caller what happened
  • Countdown pauses on hover and focus-within, and the progress bar holds rather than restarting
  • Swipe or drag to dismiss, with a velocity-aware throw and an elastic spring-back
  • Capped visible stack: the rest tuck behind a "+N more" chip that expands on hover, focus or tap
  • toast.promise() morphs one toast through loading, success and error
  • Tab reaches every toast, Escape dismisses it, and focus lands on a neighbour instead of nowhere
  • toast:show / action / dismiss / update / expand / collapse events on the stack
  • GSAP core only, and light and dark themes on one token list

Perfect for

4 use cases
  • Success and error feedback in web apps
  • Destructive actions that need an Undo window
  • Upload, deploy and save flows with a loading-to-result state
  • Live activity feeds where several notices arrive at once

How it works

3 sections

The countdown is a tween, not a timeout

Each toast's lifetime is a linear GSAP tween scrubbing its progress bar from full to empty. Because it is a tween it can be paused and resumed, so hovering the stack or tabbing into it holds the bar exactly where it stands and leaving carries on from there. A toast that is tucked behind the "+N more" chip is paused too: something nobody can read should not be counting down.

Throw it away, or let it spring back

Pointer events on the card track net displacement, so a three-pixel wobble is still a tap and the action button keeps working on touch. Past a third of the card's width, or past a velocity threshold, the card is thrown out in the direction it was moving and the stack closes the gap; short of that it springs back on an elastic ease and its x is reset to a real zero, so the next tween on that card never starts from a stale offset.

One card, several states

toast.promise() shows a single loading toast, then rewrites it in place: the card's height tweens from the old measurement to the new one while the icon spins in and the text lifts, so a loading notice becoming a success reads as one object changing rather than two notices swapping. The same update() call is public, so any toast can be morphed later.

Difficulty Intermediate
Includes HTML + JS + CSS source, documentation, AI setup prompt, lifetime updates

Lighthouse, as measured

Google Lighthouse on this UI element's demo, from the latest scan. A measurement of the demo as shipped, not a promise for your page.

Accessibility
100
Best practices
100

No performance score, on purpose. That figure depends on how you deploy: your server's compression and caching, your CDN, the connection and the device doing the test, none of which the code controls. The same page can score very differently on two consecutive runs, so measure it where it will live.

Paid UI element

Purchase to unlock the code.

Buying Toast Notifications opens the HTML, CSS and JavaScript source, the full documentation, an AI setup prompt for your editor, and every update we ship to it. Standard license: unlimited personal and commercial projects. Every paid product is tested for desktop and mobile layouts, reduced-motion handling, animation cleanup and keyboard controls wherever there is something to operate.

£10 Standard license, unlimited projects

Browse UI elements

Or the whole library: the Vault, £99, one payment.

Documentation

Quick Start

1. Add to your HTML <head>:

Code snippet omitted: it ships with the download.

2. Add before the closing </body> tag:

Code snippet omitted: it ships with the download.

3. Add the component markup (the block marked <!-- Component starts here --> in index.html). It is one empty element:

Code snippet omitted: it ships with the download.

data-toast-stack is what the script looks for. data-max-visible (default 3) is how many toasts stay in the column before the rest tuck behind the chip; data-duration (default 4500) is the default lifetime in milliseconds. Everything else is created by the script.

4. Fire a toast:

Code snippet omitted: it ships with the download.

What's Included

  • index.html: the demo page, the component markup and the two theme blocks
  • assets/style.css: the component, its five type accents and three complete looks
  • assets/script.js: readable, commented GSAP core source with the public API and cleanup
  • assets/script.min.js: minified production script
  • thumbnail.html: build-only capture state

Using It With Your Own Design

What the component needs from your markup: one element carrying data-toast-stack. That is all. It builds its own cards, its own "+N more" chip and its own icons.

What is only the demo's furniture: the toolbar strip (.showcase-toolbar), the short .stage-doc article the toasts land over, and the Google Font link. Delete all of it; none of it is part of what you bought.

CSS the component depends on: do not put a CSS transform on .toast-card or on .toast-progress — GSAP owns those, and a CSS transform underneath one is read as a pixel offset it never returns from. (transform-origin on the progress bar is fine, and the translateX on .toast-stack itself is safe because GSAP never touches the container.) Keep --extra-sign defined: it is 1 when the stack sits at the bottom of the screen and -1 when it sits at the top, and it is how the script knows which way to tuck the collapsed cards without ever reading the variant name.

Themes

Two themes, light and dark, set with one attribute. They are the same design at two token values: every colour, radius, shadow, the type accents and the stack's placement are CSS custom properties defined in body[data-variant="light"] and re-valued in body[data-variant="dark"] in assets/style.css, so the script is identical across both and never reads the attribute.

Code snippet omitted: it ships with the download.

Leaving the attribute off gives you light. The demo's toolbar and the ?variant=dark URL parameter only set this attribute; neither is part of the component.

Re-value for your brand: the ground scale (--ground, --ground-2, --raised, --hover), the ink scale (--ink, --ink-2, --ink-3), the hairlines (--line, --line-strong), the accent pair (--accent, --accent-ink, --accent-text), --shadow, --font and the radii (--radius, --radius-sm, --radius-xs). The five type accents (--type-default/success/error/warning/info/loading) are status colours and stay muted. Placement is four properties (--stack-top/bottom/left/right) plus --stack-direction; if you move a stack to the top of the screen, set --extra-top: 0, --extra-bottom: auto and --extra-sign: -1 with it. Nothing in assets/script.js changes, and no tween hard-codes a colour.

How It Works

The countdown is a tween, not a timeout. Each toast's lifetime is a linear tween scrubbing its progress bar, so it can be paused and resumed: hovering the stack or tabbing into it holds the bar where it stands, and leaving carries on from there. A toast collapsed behind the chip is paused too, because something nobody can read should not be counting down.

Throw it away, or let it spring back. Pointer events track net displacement, so a small wobble is still a tap and the action button keeps working on touch. Past a third of the card's width, or past a velocity threshold, the card is thrown out in the direction it was moving; short of that it springs back on an elastic ease, its x is reset to a real zero and its remaining time resumes.

One card, several states. toast.promise() shows a single loading toast and then rewrites it in place, tweening the card's height from the old measurement to the new one while the icon spins in and the text lifts.

The API

window.toast is the first stack on the page.

Code snippet omitted: it ships with the download.

show() (and every typed shortcut) returns a handle:

Code snippet omitted: it ships with the download.

The promise helper takes a promise (or a function returning one) and morphs one toast through its states. Each message can be a string, an options object, or a function receiving the resolved value or the error:

Code snippet omitted: it ships with the download.

Events. The stack dispatches toast:show, toast:update, toast:action, toast:dismiss, toast:expand and toast:collapse, all bubbling, with detail.id, detail.type and (where it applies) detail.reason and detail.action:

Code snippet omitted: it ships with the download.

window.spawnToast(title, message) is kept from the first release so existing calls keep working.

Accessibility

  • Live regions follow the type. An error toast is role="alert" with aria-live="assertive"; every other type is role="status" with aria-live="polite". Both are aria-atomic, so the title and message are read as one notice.
  • Keyboard. Every visible toast is a tab stop. Tab reaches it, its action button and its close button; Escape on a focused toast dismisses it; Escape elsewhere in the stack collapses an expanded pile. The "+N more" chip is a real button with aria-expanded.
  • Focus is never stranded. Dismissing a focused toast moves focus to the neighbouring toast, or back to whatever was focused before you entered the stack if that was the last one.
  • The countdown pauses on focus-within, not just on hover, so a keyboard user gets the same reading time a mouse user does.
  • Collapsed toasts are aria-hidden and out of the tab order while they are tucked behind the chip, so screen reader users are not walked through cards they cannot see.
  • Coarse pointers get no hover-only state: the chip expands the pile on tap, and the close and action targets grow.
  • Under prefers-reduced-motion: reduce toasts appear and leave without animation, the loading spinner and the indeterminate bar stop, and the countdown still runs.

Customisation

  • Colours, radii, shadows, the five type accents and the stack's placement are custom properties on each body[data-variant] block in assets/style.css.
  • Timings and eases are the gsap.to / gsap.fromTo calls in assets/script.js; the dismiss thresholds are the two lines in attachDrag.
  • The expanded pile shows up to twice data-max-visible toasts, so a stack can never grow taller than the screen; that multiplier is visibleLimit().

Requirements

  • GSAP 3.12+ (the demo uses 3.15.0; core only, no plugins)
  • No build step, no framework

Worked examples, the events and programmatic API, and the class reference ship with the download, alongside the full source.