Skip to content

Toast

A transient message in a live region, paused while it has focus or the pointer.

Preview

Code

The three render the same class names, the same ARIA and the same data attributes. That is checked when this site builds: a class in any of these samples that neither the markup contract nor the shipped stylesheet defines fails the build.

<div class="wsu-toasts" role="region" aria-label="Notifications">
  <div class="wsu-toast wsu-alert--success" role="status">
    <svg class="wsu-icon" aria-hidden="true"><use href="/assets/wayne-ui/icons.svg#wsu-circle-check"/></svg>
    <div class="wsu-alert__body">
      <span class="wsu-sr-only">Success:</span>
      <p class="wsu-alert__title">Course added</p>
      CSC 2110 is on your schedule.
    </div>
    <button class="wsu-btn wsu-btn--icon wsu-btn--ghost wsu-btn--sm" type="button">
      <span class="wsu-sr-only">Dismiss notification</span>
      <svg class="wsu-icon" aria-hidden="true"><use href="/assets/wayne-ui/icons.svg#wsu-x"/></svg>
    </button>
  </div>
</div>

Why it works this way

  • The container is a labeled region that pauses its timers on mouseenter and focusin. A message that disappears while someone is reading it or tabbing to its dismiss button fails 2.2.1. That queue, timer and pause behavior lives in packages/vue/src/composables/toasts.js, on the Vue path only.
  • A toast is the wrong place for anything the user must act on. If it matters, it belongs on the page.
  • <x-wsu::toast> and <x-wsu::toasts> exist on the Blade path and render the same markup, but carry no script of their own: nothing sets a timer, pauses on hover or focus, or wires the dismiss button, since the shared runtime a Blade page loads has no toast queue the way it has a drawer or a countdown. A Blade page that has just done something is usually better served by <x-wsu::alert>, which needs no script and stays on the page.

Accessibility

  • role="status" normally, role="alert" for the danger variant (4.1.3).
  • Timers pause on hover and focus, on the Vue path that runs them (2.2.1).
  • Dismiss is a real button with a name (4.1.2); on the Blade path nothing is wired to press it yet.

Success criteria in brackets refer to WCAG 2.2. Every one of them is checked by axe-core in both themes at three viewport widths before this page can be published. See Accessibility for what the gates are.

Props

Blade

AttributeDefaultWhat it does
variant'info'info, success, warning or danger. danger sets role="alert"; the rest set role="status".
titlenullRendered above the body.
dismissLabel'Dismiss notification'Accessible name for the close button, which has no script wired to it on this path.

Vue

PropType and defaultWhat it does
Toasts labelString, 'Notifications'Names the live region.
variantString, 'info'info, success, warning or danger.
title / messageString, ''Title is optional, message is not.
dismissLabelString, 'Dismiss notification'Accessible name for the close button.