axi0motion

Toast

Short messages that stack in a corner, burn a thin fuse for the time they have left, spread out under the pointer and swipe away.

  • enhancer
  • notification
  • message
  • swipe
  • timer
  • alert
  • since 0.2

Background Studio: tune it below, then copy the code

Your system asks for reduced motion: the demo shows its final state and nothing moves.

Live demo

Toast example

Controls

6000 ms

Code

It follows the controls above: change an option and the code changes with it.

<link rel="stylesheet" href="/axi0/motion/motion.css?v=6">
<script src="/axi0/motion/motion.js?v=10" defer></script>

<div class="demo-row">
  <button type="button" class="demo-btn" data-motion="toast" data-motion-inline="true" data-motion-show="true" data-motion-tone="success" data-motion-title="Draft saved" data-motion-text="A copy stays on this device too.">Save draft</button>
  <button type="button" class="demo-btn" data-motion="toast" data-motion-inline="true" data-motion-text="Invite sent to Sam" data-motion-action="Undo">Send invite</button>
  <button type="button" class="demo-btn" data-motion="toast" data-motion-inline="true" data-motion-tone="error" data-motion-title="Upload failed" data-motion-text="The file is over 25 MB.">Upload</button>
</div>

The wrappers: Toast.tsx (React, TypeScript) and Toast.vue (Vue). Both render the same attributes as the HTML; the loader does the rest.

Options

AttributeDefaultWhat it does
data-motion-textSavedthe message
data-motion-titleautoa bold first line (optional)
data-motion-toneinfothe icon and color; error toasts are read at once
data-motion-actionautoa button inside the toast, such as Undo (it fires a toast-action event on the trigger)
data-motion-duration6000how long it stays; 0 keeps it until it is closed
data-motion-inlinefalsestack the toasts at the bottom of the trigger's parent instead of the page
data-motion-showfalseraise one toast as soon as the trigger comes into view

Accessibility

- Toasts live in a labeled region ("Notifications") whose list is a polite live region, so each new message is read once; error toasts use role="alert" and are read at once. - Every toast has a Dismiss button; Escape closes the focused toast and focus moves to the next one (or back to where it was). Alt+T jumps to the newest toast on the page. - The time left stops running while the pointer rests on the stack, while focus is inside it and while the tab is hidden, so nobody loses a message they are reading. Use duration="0" for messages that must stay. - Swiping down closes a toast on touch screens; every swipe has a button that does the same. - Reduced motion hides the fuse and shows and hides toasts with no movement; the timer still runs. Reduced motion shows every state at once, with no movement, and stops anything that would move on its own. Frame loops and CSS animations pause off screen and in hidden tabs. Only transform, opacity and paint animate, so nothing around it moves.

Size

toast.js is 3.0 KB gzip, with components-kit.js 3.9 KB it needs. A page loads the loader (2.7 KB) and core.js (1.4 KB) once, whatever it uses.