Skip to content

Loading

An in-progress marker with a text label beside it.

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.

<span class="wsu-loading wsu-loading--brand" role="status">
  <span class="wsu-loading__spinner" aria-hidden="true"></span>
  Saving changes…
</span>

Why it works this way

  • The same division of labor as StatusDot: the spinner is decorative and aria-hidden, the word is what tells anyone, sighted or not, what is happening (1.4.1).
  • role="status" makes the whole thing a polite live region, so replacing the label, "Saving changes…" to "Changes saved", is announced without moving focus.
  • label is required on every path. Blade and the standalone function throw rather than render an unnamed spinner (4.1.2).

Accessibility

  • Text plus the spinner, never the spinner alone (1.4.1).
  • role="status" announces a change in the label without an interruption (4.1.3).

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
labelrequiredThrows if omitted (WCAG 4.1.2).
variant'brand'brand, accent, success or danger.

Vue

PropType and defaultWhat it does
labelString, requiredThrows if omitted (WCAG 4.1.2).
variantString, 'brand'brand, accent, success or danger.

In the markup contract

contract/markup-contract.json is extracted from the two static templates and every package tests against it. This is what it records for .wsu-loading.

TemplateElementsAccessibility attributesUses
internal apps/examples/static-html/index.htmlspanrole1
public apps/examples/static-html/public-app.htmlspanrole1