Skip to content

Text rotate

A short list of facts, shown one at a time. An announcement strip, not a marketing carousel.

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-rotator" data-wsu-rotate data-wsu-rotate-interval="6000">
  <p class="wsu-rotator__label" id="announcements-label">Announcements</p>

  <ul class="wsu-rotator__list" aria-labelledby="announcements-label">
    <li class="wsu-rotator__item" data-wsu-rotate-active>2 seats just opened in CSC 2110.</li>
    <li class="wsu-rotator__item">Advising hours are extended through Friday.</li>
    <li class="wsu-rotator__item">Financial aid disbursements begin January 15.</li>
  </ul>

  <button type="button" class="wsu-btn wsu-btn--icon wsu-btn--ghost wsu-rotator__pause" data-wsu-rotate-pause aria-pressed="false">
    <span class="wsu-rotator__pause-state" data-wsu-rotate-pause-state="running">Pause</span>
    <span class="wsu-rotator__pause-state" data-wsu-rotate-pause-state="paused" hidden>Resume</span>
  </button>
</div>

Why it works this way

  • The rotation carries no script of its own. data-wsu-rotate and the attributes beside it are read by the shared runtime in @waynestate/wayne-ui-css/theme, the same module the static, raw PHP and Blade paths load directly, so this is one implementation rather than four. On the Vue path that runtime is wired up by useChromeRuntime, which AppShell calls, so a TextRotate rendered outside an AppShell shows only its first item and never advances.
  • Every item is real markup in the page the whole time. Only which one carries data-wsu-rotate-active, and therefore which one the stylesheet renders at full opacity, ever changes. A screen reader user who reaches this control gets the whole list, in document order, rather than whichever phrase happened to be on screen when they arrived.
  • The pause button is the same WCAG 2.2.2 mechanism Countdown carries, for the same reason: this moves on its own, indefinitely, with nothing essential riding on the rotation itself.

Accessibility

  • Every item stays in the accessibility tree, so nothing here depends on catching a phrase before it rotates away (1.3.1).
  • A pause control for content that moves on its own past five seconds (2.2.2).
  • The list is labeled, so a screen reader announces what the rotating items are examples of.

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
items[]At least two, or the second item never rotates in.
label'Announcements'Names the list for screen reader users.
interval5000Milliseconds between rotations.
idgenerated from labelid of the label paragraph, via WSU\WayneUi\Support\UniqueId. Set it to control or reuse the id.

Vue

PropType and defaultWhat it does
itemsArray, []At least two, or the second item never rotates in.
labelString, 'Announcements'Names the list for screen reader users.
intervalNumber, 5000Milliseconds between rotations.

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-rotator.

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