Skip to content

Accessibility

Evolve targets WCAG 2.2 at level AA. Most of that is built into the storefront components, and automated checks keep it there. The rest depends on your brand, your content and your app shell, so your project owns it. This page covers the three in that order.

The form and overlay components in @evolve-storefront/ui are built on React Aria Components. React Aria gives them their keyboard support, focus handling and ARIA roles, so the feature packages do not write that themselves. A storefront uses one overlay library: two would fight over focus and over the page behind a dialog.

Some behavior goes further than the primitives:

  • Forms. A field with an error sets aria-invalid, and the field is described by its error message. The submit button stays enabled, so a shopper who submits too early is told what is missing instead of being stuck. See Forms.
  • Announcements. Adding to the cart, and undoing the removal of a line, are announced to screen readers through a live region.
  • The mega menu. Its items are disclosure buttons, not a menu. The arrow keys and Home move between them, and Escape closes the panel and puts focus back on the item that opened it.
  • Focus. Every focusable control shows a ring in your brand’s --color-ring when it is focused from the keyboard.
  • Motion. The carousel’s scrolling and the mega menu’s panels follow the shopper’s reduced-motion setting.
  • Language. The reference sites set lang on the page for each locale.
  • Images. An image from the CMS without alt text renders with an empty alt, which marks it as decorative.

Four checks run on their own, from the components up to whole pages.

Each component story runs as a test in a real browser. In each run, the accessibility addon checks the story with axe, and a violation fails the test. A second check measures every clickable target against WCAG 2.5.8, at least 24 by 24 pixels, at a desktop width and at a phone width of 375 pixels. Both run in the storefront’s CI on every push.

A story can be exempted while its fix is pending. Each exemption must name the issue that tracks the fix, or a test fails.

The conformance matrix in Storybook lists every WCAG 2.2 AA criterion per kind of component, and how each one is met: by the primitive, by a story, by axe, by a manual check, or by your project.

The components take their colors from your brand’s design tokens, so a component that passes with the default brand can fail with yours. Add a contrast test to your project:

pnpm exec evolve add brand-contrast

It writes brand-contrast.test.ts next to your brand stylesheet. The test runs with your other unit tests and checks each pair of tokens in every block of the stylesheet, a dark surface included:

Pair Minimum ratio
Text on its background: foreground, muted, primary, secondary, highlight, brand, destructive, success 4.5:1
The input border and the focus ring on the background 3:1

Style and brand shows how to read a failure.

Each end-to-end test in the reference sites ends with an accessibility check of the page it leaves behind:

await expect(page).toBeAccessible();

toBeAccessible comes from @evolve-storefront/testing. It runs axe against the WCAG 2.0, 2.1 and 2.2 rules at levels A and AA. A failure is fixed, not excluded: excluding a selector is only for a third party’s iframe. Each reference site has a unit test that fails when a journey does not end with the check, and the journeys that evolve add e2e writes end with it too. See Testing for how the journeys are set up.

A crawl runs the same check over every content page in the sitemap, and over twenty of its products.

The storefront and the reference sites lint with Biome’s recommended rules, which include its accessibility rules. Each exception in the code says why it is there.

Some criteria cannot be met by a component, because they depend on your content, your brand or your app shell:

Criterion Why it is yours
1.1.1 Non-text Content Alt text for product and CMS images is content.
1.2.2 Captions Captions belong to the video.
1.4.3 Contrast and 1.4.11 Non-text Contrast Colors are your brand’s tokens. Run the brand contrast check.
2.4.1 Bypass Blocks A skip link and the landmarks are part of your app shell.
2.4.2 Page Titled Your routes set the page titles.
3.1.1 Language of Page Your root layout sets lang.
3.2.3 Consistent Navigation Your header and footer hold the navigation.
3.2.6 Consistent Help You decide where help or chat sits.

Automated checks find only part of what WCAG asks. Before a release, test the journeys that changed by hand:

  • with the keyboard only;
  • with a screen reader;
  • at 400% zoom;
  • with reduced motion turned on.

If you publish an accessibility statement, base it on these checks and on the criteria above.