Menu


Toast


A short-lived message that floats above the page: the alert's anatomy, raised, arriving in a corner and leaving on its own after a few seconds unless someone is reading it.

Customize the preview


Choices
Show
View

Changes saved

Website redesign was updated a moment ago.

Options


Toast options
ChoiceValuesDefaultWhat it does
tonesmbk-toast--tone-<value>defaultinfosuccesswarningdangerdefault
Neutral, or one of the four feedback families on their subtle surface, each with its own icon.

Partssmbk-toast__iconsmbk-toast__bodysmbk-toast__titlesmbk-toast__descriptionsmbk-toast__actionsmbk-toast__dismisssmbk-toast__region

Examples


Usage

The alert's anatomy, raised to the highest elevation.

Changes saved

Website redesign was updated a moment ago.

Tones

Five tones, each with its own icon, as the alert.

Changes saved

Website redesign was updated.

Update available

A new version is ready to install.

Invite sent

Tom will get an email shortly.

Connection unstable

We keep retrying in the background.

With action

One small action, typically undo.

Saved

Your changes are stored.

Dismissible

A close control appears when a dismiss handler is given.

Link copied

Anyone with the link can view this project.

Toast region

The page shows toasts through one region: they appear in the corner, stay six seconds unless pointed at or focused, and wait for their action if they have one.

Guidelines


Purpose

A brief message that floats above the page to confirm something just happened — saved, sent, copied — and then leaves. It has the alert's anatomy and the highest elevation, because it is not part of the page.

When to use

  • Confirming an action whose result is not otherwise visible.
  • A brief notice that needs no reply.

When not to use

  • Anything the person must read or act on. Use an alert, or a dialog.
  • Errors that block a task. Those belong where the task is.

Usage rules

Do

  • Keep it to one line where possible.

Don't

  • Show a toast for something the person did not do, unless it is a status change they are waiting for.

Invite sent

Tom will get an email shortly.

Do

Keep a toast to one short line, so it can be read before it goes.

Invite sent

Tom Reyes will get an email with a link to join Website redesign. The link works for seven days, after which you can send a new invite from the members page or ask an owner to add him.

Don't

A paragraph in a toast disappears before the reader gets to the end.

Anatomy

The same parts as the alert: icon, body with title and description, action, dismiss. Each tone has its own icon, as the alert's, and the cross sits in a box big enough to press. The block is raised and has a fixed width.

  • The region part, where a page's toasts appear: the corner at the end of the viewport's foot, one under another, the newest last. On a phone it spans the viewport less its inset, and so do its toasts.

Behavior

A toast region shows, times and closes a page's toasts. Put ToastRegion round the page once, as it loads, and call useToasts().show() anywhere inside it with the toast's tone, title, description and action; it returns an id that dismiss() takes.

  • A toast stays six seconds, then leaves. A danger toast, and a toast with an action, stay until they are closed. A toast can set its own time, or none.
  • While the pointer is on the region or focus is in it, every timer stops, and each starts again with the time it had left once the pointer and focus have gone. A page in a tab nobody is looking at holds them too.
  • Escape closes the toast focus is in, and focus moves on to the next toast, or back where it was before it went into the region.
  • Three toasts show at once; the others wait their turn and show as earlier ones leave.

A toast fades in and rises a spacing step into place when it appears, and fades out dropping a smaller step as it leaves. Under reduced motion it fades in and out in place, without rising or dropping.

On its own, without a region, the component renders one toast that stays until the page removes it or hides it with the hidden attribute, which plays the same exit.

Accessibility


What it does for you

  • Each toast's title and description are announced as it shows, without moving focus: politely, or at once for a danger toast. Two hidden announcers inside the region say them, so none is said twice. A toast in a region has no role of its own; the region is a named landmark.
  • A toast on its own carries the status role itself, or the alert role when it is a danger toast.
  • F6 moves focus to the newest toast while any shows, so a toast with an action can be reached without tabbing through the page, and F6 again goes back where focus was. The region names the key for screen readers.
  • A toast with an action stays until it is closed, unless given a time. A danger toast stays until closed, so it cannot vanish unread.
  • While the pointer is on the region or focus is in it, every timer stops, so a toast does not leave while it is being read or reached.
  • Escape closes the toast focus is in, and focus moves on to the next toast, or back where it was before it went into the region.

What you must do

  • Put the region in the page as it loads, never with its first toast: it must be there before the first toast arrives, or that toast is not announced.
  • Never let a toast be the only place a piece of information appears, because it leaves on its own.
  • Give a toast with a time one long enough to reach the action by keyboard.
  • Put an error the reader must act on where the task is, not in a toast.
  • In plain markup, give the region the status role, aria-atomic="false", so each toast is announced alone, and a name, and give the toasts in it no role; put a danger toast's words in an element with the alert role that is in the page from the start. Timing, holding and Escape are then the page's own script, and must keep to the rules above.
  • Give the page's own words for everything it says by itself, such as the dismiss cross's name, which keeps its English until you do; a page in another language can change it.

How to test

  • With a screen reader, show a toast: it is announced without focus moving. Show one more after the page has loaded and check it is announced too.
  • Tab into the region: the timers stop, the dismiss cross and any action take focus with a focus ring, and Escape closes the toast.
  • Show a toast and press F6: focus moves to it. Press F6 again: focus goes back. Show a danger toast: it is announced at once, interrupting.
  • Show a danger toast and one with an action: both stay until closed.
  • With reduced motion on, a toast fades in and out in place.

Keyboard

Toast keys
KeyWhat it does
F6
While a toast shows, moves focus to the newest toast's action or dismiss cross; from inside the region, back to where focus was.
Tab
Moves focus to a toast's action and its dismiss cross.
EnterorSpace
Presses the action or the dismiss cross.
Escape
Closes the toast focus is in and moves focus to the next toast, or back to where it was before it entered the region.

Source


The files the toast is made of. Its folder on GitHub (opens in a new tab) holds them with its wrapper and its document.

Stylesheet
toast.css
/* smbk-toast — Toast. Figma "Toast" 4209:20131. The alert, raised to float above the page.
 * It rises into place as it appears and drops away as it is hidden (motion rules at the end). */

.smbk-toast {
  /* The neutral tone; each feedback tone sets these again below (the tone recipe). */
  --smbk-tone-surface: var(--smbk-color-surface-default);
  --smbk-tone-border: var(--smbk-color-border-rim);
  --smbk-tone-text: var(--smbk-color-text-default);
  --smbk-tone-icon: var(--smbk-color-icon-subtle);
  box-sizing: border-box;
  display: flex;
  align-items: flex-start;
  gap: var(--smbk-space-inline-lg);
  width: var(--smbk-size-content-sm);
  max-width: 100%;
  padding: var(--smbk-space-inset-lg) var(--smbk-space-inset-xl);
  border: var(--smbk-border-width-hairline) solid var(--smbk-tone-border);
  border-radius: var(--smbk-radius-container-sm);
  background: var(--smbk-tone-surface);
  color: var(--smbk-tone-text);
  box-shadow: var(--smbk-elevation-overlay);
}

/* The icon's box is as tall as the title's line, so the icon sits on the first line's middle.
   The title sits on its text with no gap: the line heights give the air. */
.smbk-toast__icon { display: inline-flex; flex-shrink: 0; align-items: center; height: calc(var(--smbk-typography-label-lg-font-size) * var(--smbk-typography-label-lg-line-height)); color: var(--smbk-tone-icon); font-size: var(--smbk-size-icon-md); }
.smbk-toast__body { display: flex; flex: 1 1 0; flex-direction: column; gap: var(--smbk-space-text-label); min-width: 0; }
.smbk-toast__title { margin: 0; font-family: var(--smbk-typography-label-lg-font-family); font-size: var(--smbk-typography-label-lg-font-size); font-weight: var(--smbk-typography-label-lg-font-weight); line-height: var(--smbk-typography-label-lg-line-height); letter-spacing: var(--smbk-typography-label-lg-letter-spacing); text-transform: var(--smbk-typography-label-lg-text-transform); }
.smbk-toast__description { margin: 0; color: var(--smbk-color-text-subtle); font-family: var(--smbk-typography-body-sm-font-family); font-size: var(--smbk-typography-body-sm-font-size); font-weight: var(--smbk-typography-body-sm-font-weight); line-height: var(--smbk-typography-body-sm-line-height); letter-spacing: var(--smbk-typography-body-sm-letter-spacing); }
.smbk-toast__action { display: flex; flex-shrink: 0; flex-wrap: wrap; gap: var(--smbk-space-inline-md); }

/* .smbk-toast__dismiss: the alert's cross, the small press box shared in press-box/press-box.css, with its focus ring
   and its press area on a touch screen. */

/* ---- feedback tones: the tone recipe, each family's subtle surface, its border, its text and its icon ---- */

.smbk-toast--tone-info { --smbk-tone-surface: var(--smbk-color-feedback-info-surface-subtle); --smbk-tone-border: var(--smbk-color-feedback-info-border); --smbk-tone-text: var(--smbk-color-feedback-info-text-on-subtle); --smbk-tone-icon: var(--smbk-color-feedback-info-icon); }
.smbk-toast--tone-success { --smbk-tone-surface: var(--smbk-color-feedback-success-surface-subtle); --smbk-tone-border: var(--smbk-color-feedback-success-border); --smbk-tone-text: var(--smbk-color-feedback-success-text-on-subtle); --smbk-tone-icon: var(--smbk-color-feedback-success-icon); }
.smbk-toast--tone-warning { --smbk-tone-surface: var(--smbk-color-feedback-warning-surface-subtle); --smbk-tone-border: var(--smbk-color-feedback-warning-border); --smbk-tone-text: var(--smbk-color-feedback-warning-text-on-subtle); --smbk-tone-icon: var(--smbk-color-feedback-warning-icon); }
.smbk-toast--tone-danger { --smbk-tone-surface: var(--smbk-color-feedback-danger-surface-subtle); --smbk-tone-border: var(--smbk-color-feedback-danger-border); --smbk-tone-text: var(--smbk-color-feedback-danger-text-on-subtle); --smbk-tone-icon: var(--smbk-color-feedback-danger-icon); }

/* ---- the region: where the page's toasts appear, in the corner at the end of the viewport's
   foot, one under another, the newest last. It is in the page before the first toast arrives,
   with the hidden announcers that say each toast inside it, and takes no room or pointer while it is
   empty. On a phone it spans the viewport less its inset, and so do its toasts. ---- */

.smbk-toast__region {
  position: fixed;
  inset-block-end: var(--smbk-space-inset-xl);
  inset-inline-end: var(--smbk-space-inset-xl);
  z-index: var(--smbk-layer-critical);
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--smbk-space-stack-sm);
  max-width: calc(100% - 2 * var(--smbk-space-inset-xl));
  margin: 0;
  padding: 0;
  pointer-events: none;
}

.smbk-toast__region > * {
  pointer-events: auto;
}

@container style(--smbk-layout: narrow) {
  .smbk-toast__region {
    inset-inline-start: var(--smbk-space-inset-xl);
    align-items: stretch;
  }

  .smbk-toast__region > .smbk-toast {
    width: auto;
  }
}

/* ---- motion: a toast fades in and rises a spacing step into place with the enter purpose when
   it appears, and fades out dropping a smaller step with the exit purpose when the page hides it
   with the hidden attribute. Its display changes at the end of the exit, so it stays drawn while
   it leaves; a toast removed from the page outright simply goes. Under reduced motion it fades in and out in
   place, without rising or dropping. ---- */

.smbk-toast {
  transition-property: opacity, translate, display;
  transition-duration: var(--smbk-motion-enter-duration);
  transition-timing-function: var(--smbk-motion-enter-easing);
  transition-behavior: allow-discrete;
}

/* The toast's own display would otherwise outweigh the hidden attribute. */
.smbk-toast[hidden] {
  display: none;
  opacity: 0;
  translate: 0 var(--smbk-space-8);
  transition-duration: var(--smbk-motion-exit-duration);
  transition-timing-function: var(--smbk-motion-exit-easing);
}

@starting-style {
  .smbk-toast {
    opacity: 0;
    translate: 0 var(--smbk-space-16);
  }
}

@media (prefers-reduced-motion: reduce) {
  .smbk-toast {
    transition-property: opacity, display;
  }

  .smbk-toast[hidden] {
    translate: none;
  }
}
Tokens it reads
Toast tokens
Token and CSSValuePreviewFoundation
size.target.min--smbk-size-target-min24pxSize
typography.label-lg--smbk-typography-label-lg-font-family--smbk-typography-label-lg-font-size--smbk-typography-label-lg-font-weight--smbk-typography-label-lg-line-height--smbk-typography-label-lg-letter-spacing--smbk-typography-label-lg-text-transformfontFamily: Geist, Geist Fallback, system-ui, sans-seriffontSize: 16pxfontWeight: 500lineHeight: 1.4letterSpacing: 0px

The quick brown fox

Typography
size.icon.md--smbk-size-icon-md20pxSize
radius.full--smbk-radius-full9999pxRadius
focus.ring.width--smbk-focus-ring-width2pxFocus
color.border.focus--smbk-color-border-focuslight: #cc0d0ddark: #f34336changes with themeColor
focus.ring.offset--smbk-focus-ring-offset2pxFocus
size.target.comfortable--smbk-size-target-comfortable44pxSize
color.surface.default--smbk-color-surface-defaultlight: #f3f5f8dark: #181a1cchanges with themeColor
color.border.rim--smbk-color-border-rimlight: #ffffffe6dark: #ffffff0dchanges with themeColor
color.text.default--smbk-color-text-defaultlight: #232527dark: #e7ebf0changes with themeColor
color.icon.subtle--smbk-color-icon-subtlelight: #4e555edark: #c4cdd8changes with themeColor
space.inline.lg--smbk-space-inline-lgcomfortable: 12pxcompact: 8pxchanges with densitySpacing
size.content.sm--smbk-size-content-sm480pxSize
space.inset.lg--smbk-space-inset-lgcomfortable: 12pxcompact: 8pxchanges with densitySpacing
space.inset.xl--smbk-space-inset-xlcomfortable: 16pxcompact: 12pxchanges with densitySpacing
border-width.hairline--smbk-border-width-hairline1pxBorder width
radius.container.sm--smbk-radius-container-sm8pxRadius
elevation.overlay--smbk-elevation-overlaylight: 0px 12px 16px 2px #373d431a, 0px 2px 8px 0px #373d4326dark: 0px 12px 16px 2px #00000026, 0px 2px 8px 0px #00000033Elevation
space.text.label--smbk-space-text-label0pxSpacing
color.text.subtle--smbk-color-text-subtlelight: #4e555edark: #9ba5b1changes with themeColor
typography.body-sm--smbk-typography-body-sm-font-family--smbk-typography-body-sm-font-size--smbk-typography-body-sm-font-weight--smbk-typography-body-sm-line-height--smbk-typography-body-sm-letter-spacing--smbk-typography-body-sm-text-transformfontFamily: Geist, Geist Fallback, system-ui, sans-seriffontSize: 14pxfontWeight: 400lineHeight: 1.5letterSpacing: 0px

The quick brown fox

Typography
space.inline.md--smbk-space-inline-mdcomfortable: 8pxcompact: 6pxchanges with densitySpacing
color.feedback.info.surface-subtle--smbk-color-feedback-info-surface-subtlelight: #e3ebfedark: #162352changes with themeColor
color.feedback.info.border--smbk-color-feedback-info-border#557bffColor
color.feedback.info.text-on-subtle--smbk-color-feedback-info-text-on-subtlelight: #2f4ab8dark: #b8ccffchanges with themeColor
color.feedback.info.icon--smbk-color-feedback-info-iconlight: #3b5ce3dark: #7fa0ffchanges with themeColor
color.feedback.success.surface-subtle--smbk-color-feedback-success-surface-subtlelight: #dffddfdark: #0a2d0echanges with themeColor
color.feedback.success.border--smbk-color-feedback-success-border#269936Color
color.feedback.success.text-on-subtle--smbk-color-feedback-success-text-on-subtlelight: #016317dark: #8ddf90changes with themeColor
color.feedback.success.icon--smbk-color-feedback-success-iconlight: #037a1fdark: #54b85bchanges with themeColor
color.feedback.warning.surface-subtle--smbk-color-feedback-warning-surface-subtlelight: #ffe6dbdark: #431b07changes with themeColor
color.feedback.warning.border--smbk-color-feedback-warning-border#da601aColor
color.feedback.warning.text-on-subtle--smbk-color-feedback-warning-text-on-subtlelight: #913900dark: #febea2changes with themeColor
color.feedback.warning.icon--smbk-color-feedback-warning-iconlight: #b14904dark: #fa8349changes with themeColor
color.feedback.danger.surface-subtle--smbk-color-feedback-danger-surface-subtlelight: #fee5e1dark: #4b130echanges with themeColor
color.feedback.danger.border--smbk-color-feedback-danger-border#f34336Color
color.feedback.danger.text-on-subtle--smbk-color-feedback-danger-text-on-subtlelight: #a51d17dark: #febdb2changes with themeColor
color.feedback.danger.icon--smbk-color-feedback-danger-iconlight: #cc0d0ddark: #fe7d6dchanges with themeColor
layer.critical--smbk-layer-critical1400Stacking order
space.stack.sm--smbk-space-stack-smcomfortable: 8pxcompact: 6pxchanges with densitySpacing
motion.enter.duration--smbk-motion-enter-duration320msMotion
motion.enter.easing--smbk-motion-enter-easingcubic-bezier(0.16, 1, 0.3, 1)Motion
space.8--smbk-space-88pxSpacing
motion.exit.duration--smbk-motion-exit-duration200msMotion
motion.exit.easing--smbk-motion-exit-easingcubic-bezier(0.7, 0, 0.84, 0)Motion
space.16--smbk-space-1616pxSpacing
Manifest
toast.manifest.json
{
  "name": "toast",
  "block": "smbk-toast",
  "summary": "A short-lived message that floats above the page: the alert's anatomy, raised, arriving in a corner and leaving on its own after a few seconds unless someone is reading it.",
  "adapt": "css",
  "axes": {
    "tone": {
      "values": [
        "default",
        "info",
        "success",
        "warning",
        "danger"
      ],
      "default": "default",
      "description": "Neutral, or one of the four feedback families on their subtle surface, each with its own icon."
    }
  },
  "flags": {},
  "parts": [
    "icon",
    "body",
    "title",
    "description",
    "action",
    "dismiss",
    "region"
  ],
  "figmaNodeId": "4209:20131"
}