Accessibility
WCAG 2.2 Level AA is the floor, and AAA wherever the WSU palette reaches it. That is a build gate rather than a goal. Nothing in the pipeline is allow_failure and no job downgrades a violation to a warning. If a color pair, a component or an example application regresses, the gate fails.
The pipeline is defined in .gitlab-ci.yml. This GitLab instance does not yet provide runners, so until it does the same suites are run before every release rather than on every push. Same commands, same thresholds, nothing skipped.
Wayne State is a public institution. An application that is inaccessible is not a lower quality product, it is one that some people cannot use to do things they are entitled to do.
What runs, and when
| Stage | Job | What it checks |
|---|---|---|
| test | test:tokens | Every declared color pairing meets its declared minimum, in both themes. Runs before anything is built |
| test | test:vue | Component unit tests, plus axe over each component in isolation |
| test | test:php | Blade and standalone PHP output against the markup contract |
| a11y | a11y:axe | axe-core over every page of this site and both example applications |
| a11y | a11y:lighthouse | Lighthouse accessibility, which has to score 100 |
| a11y | a11y:visual | Reflow at 320px, 200% and 400% zoom, and a text-spacing override |
a11y:axe runs at three viewport widths, 320, 768 and 1440, in both themes. That is six passes per page. Most of the defects it has caught were present at one width or in one theme only.
The contrast gate
Every color pairing the system relies on is declared on the token itself, with the minimum it has to meet:
{
"foreground": "semantic.light.text.subtle",
"background": "semantic.light.surface.base",
"min": 4.5,
"note": "AA, captions and helper text only, never primary content"
}The test suite reads those declarations back and measures the ratio. There is also a coverage test, because the way a pairing escapes a contrast gate is not by failing it, it is by never being declared. Measured figures for all of them are on the Tokens page.
Body text is held to 7:1, which is AAA rather than the 4.5:1 AA floor, because the palette reaches it. Helper text and captions are held to 4.5:1. Borders and focus rings are held to 3:1, per 1.4.11.
Reflow and text spacing
a11y:visual loads each page at 320px wide and asserts the document does not scroll horizontally. It then applies the WCAG 1.4.12 text-spacing override, which is line height 1.5, paragraph spacing 2em, letter spacing 0.12em and word spacing 0.16em, and asserts nothing is clipped or overlapping.
A table is allowed to scroll inside its own box. The page body is not.
Decisions the system makes for you
These are the ones that come up most often, and the reasoning behind each.
State never rests on color alone. The current-page item carries a heavier weight as well as a fill. Status messages carry an icon and a title that says the same thing in words. A badge always has text, because a badge with no label is a colored dot.
Styling is driven off the accessible state. aria-current, aria-invalid and [open] are what the stylesheet selects on, rather than a parallel .active class. The visible state and the announced state are then one fact and cannot drift apart. 1.x emitted class="active", which says nothing to a screen reader.
Hidden means out of the tab order. A zero-width or zero-opacity control is still focusable, and landing on an invisible thing is a 2.4.3 failure that is easy to ship and hard to notice. Drawers carry hidden until they open.
A control that navigates is an <a>; a control that acts is a <button>. Styling one to look like the other is fine. Using one where the other belongs breaks middle-click, open-in-new-tab, the screen reader's list of links, and the difference between Enter and Space.
Targets are 44px. --wsu-size-tap-min is 2.75rem, which is the AAA target size in 2.5.5. --wsu-size-tap-compact is 2.25rem for controls inside a dense table, which still clears the 24px AA floor in 2.5.8.
Motion is in tokens so it can be switched off centrally.prefers-reduced-motion is handled once in base.css, which only works because no component invents its own duration.
Zoom is never disabled. No maximum-scale, no user-scalable=no. That fails 1.4.4 and is the most common accessibility defect in a mobile layout.
Testing your own application
The gates cover WayneUI. They do not cover what you build with it.
Automated tools find somewhere between a third and a half of accessibility defects. Everything below is the part they do not find, in the order it is worth doing.
- Tab through every page. Focus visible on every stop, in a sensible order, nothing invisible taking focus, and no trap you cannot Escape out of.
- Use it without a mouse for ten minutes. Open the drawer, sort a table, submit a form with errors, dismiss a dialog.
- Narrow to 320px, then zoom to 400%. The page body must not scroll sideways.
- Read one page with a screen reader. VoiceOver on macOS is Command plus F5 and costs nothing. Listen to your headings, your form labels and your error messages.
- Switch to dark and read it again.
- Turn the stylesheet off. The DOM order is the reading order, so the page should still make sense.
Then run axe. It is a floor, not a report card:
pnpm add -D @axe-core/playwrightimport AxeBuilder from '@axe-core/playwright'
const results = await new AxeBuilder({ page })
.withTags(['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa', 'wcag22aa'])
.analyze()
expect(results.violations).toEqual([])Reporting a problem
If something in WayneUI is inaccessible, open an issue on the repository, or write to adammpkins@wayne.edu if you would rather not report it in public. If something in a Wayne State application is inaccessible, the university's accessibility page has the reporting route and the contacts.
An accessibility defect in this package is treated as a defect, not an enhancement. It goes in the next patch release.
Accessibility statement
Wayne State University is committed to making its digital services usable by everyone, including people with disabilities.
Standard. WayneUI 2.0 is designed and tested against Web Content Accessibility Guidelines 2.2 Level AA. Several criteria are met at Level AAA, in particular 1.4.6 Contrast (Enhanced) for body text and 2.5.5 Target Size (Enhanced) for controls.
Scope. This statement covers the WayneUI design system: the token package, the stylesheet, the Vue components, the Blade components, the framework-free PHP helpers, and this documentation site. It does not cover applications built with WayneUI, each of which is the responsibility of the team that maintains it, nor the official university masthead and footer, which are maintained separately as @waynestate/wsuheader and @waynestate/wsufooter.
Conformance. WayneUI targets WCAG 2.2 Level AA, and the exceptions it knows about are listed under "Where it stops short" rather than in a separate report. No formal Accessibility Conformance Report is published for WayneUI, because it is internal tooling rather than a procured product, and an unaudited ACR is a liability rather than an assurance.
If your application is asked for one, note that an ACR for WayneUI would not discharge the obligation anyway. WayneUI can guarantee that a button is 44px and that a color pairing measures 7:1. It cannot know whether your error messages tell somebody what to do, whether your reading order makes sense, or whether you put a video on the page. The report has to be about your application.
How it is verified. Automated testing with axe-core and Lighthouse gates every release. Contrast is verified by measurement against declarations held on the tokens themselves. Keyboard behavior is driven and asserted in a real browser rather than inferred from markup.
What has not been verified. No assistive technology has been used against this system. There has been no testing with VoiceOver, NVDA or JAWS, and no review by a person whose job is accessibility. Everything above is a machine checking what a machine can check, which is a floor and not a substitute. A manual review is the next thing this system needs, and until it happens the conformance statement above should be read as a claim awaiting audit rather than a finding.
Limits of automated testing. No automated tool finds every barrier. Reading order, the usefulness of an accessible name, whether an error message tells someone what to do, and whether an interaction is comprehensible are all matters of judgment.
Feedback. Report a barrier through the repository issue tracker or through https://wayne.edu/accessibility/, which is the university's own route and carries whatever handling commitment the university has made. This project makes no separate commitment of its own.
Last reviewed. This statement is reviewed at every minor release.