feat(a11y): WP-01 — axe-on-every-story CI gate

Turn the interactive Storybook a11y addon into a build gate:
- @storybook/test-runner + axe-playwright over the static build
  (.storybook/test-runner.ts reads the a11y tags from story context)
- test-storybook / test-storybook:ci scripts; storybook-a11y CI job
- triage: escape-hatch a11y.disable on stories whose display:contents
  wrapper splits <ul>/<li> or <dl>/<dt>/<dd> (structural, deferred to
  WP-11/WP-12, each with justification + cross-ref)
- fix trivial violations: footer/wizard-shell contrast, text-input label,
  wizard stories missing provideApiClient

Verified: broken story fails the gate; 133 stories pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-02 19:13:18 +02:00
parent b4fb0be769
commit 97f7de4590
22 changed files with 7795 additions and 1819 deletions

View File

@@ -12,11 +12,15 @@ import { Component } from '@angular/core';
.inner{max-inline-size:var(--app-content-max);margin-inline:auto;padding:var(--rhc-space-max-3xl) var(--rhc-space-max-2xl);box-sizing:border-box;display:flex;gap:var(--rhc-space-max-3xl);flex-wrap:wrap;justify-content:space-between}
.tagline{font-style:italic;font-weight:var(--rhc-text-font-weight-semi-bold);font-size:var(--rhc-text-font-size-lg);max-inline-size:18rem}
.ministry{margin-block-start:var(--rhc-space-max-md);font-size:var(--rhc-text-font-size-sm);color:var(--rhc-color-foreground-on-primary)}
.col h2{margin:0 0 var(--rhc-space-max-md);font-size:var(--rhc-text-font-size-sm);font-weight:var(--rhc-text-font-weight-bold);text-transform:uppercase;letter-spacing:.04em}
/* CIBG's vendored h2 tag rule (dark navy, for light backgrounds) beats inherited
color regardless of specificity — restate on-primary explicitly for this dark bar. */
.col h2{margin:0 0 var(--rhc-space-max-md);font-size:var(--rhc-text-font-size-sm);font-weight:var(--rhc-text-font-weight-bold);text-transform:uppercase;letter-spacing:.04em;color:var(--rhc-color-foreground-on-primary)}
.links{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:var(--rhc-space-max-sm);font-size:var(--rhc-text-font-size-sm)}
.links a{color:var(--rhc-color-foreground-on-primary);text-decoration:none}
.links a:hover{text-decoration:underline}
.meta{inline-size:100%;border-block-start:var(--rhc-border-width-sm) solid rgb(255 255 255 / 0.25);margin-block-start:var(--rhc-space-max-xl);padding-block-start:var(--rhc-space-max-lg);font-size:var(--rhc-text-font-size-sm);opacity:.85}
/* CIBG's vendored .meta class (unrelated component, coincidental name) sets a
dark grey — override rather than rename to keep the CIBG-mirroring class name. */
.meta{inline-size:100%;border-block-start:var(--rhc-border-width-sm) solid rgb(255 255 255 / 0.25);margin-block-start:var(--rhc-space-max-xl);padding-block-start:var(--rhc-space-max-lg);font-size:var(--rhc-text-font-size-sm);opacity:.85;color:var(--rhc-color-foreground-on-primary)}
`],
template: `
<footer class="bar">

View File

@@ -35,6 +35,8 @@ export type WizardStatus = 'editing' | 'submitting' | 'submitted' | 'failed';
styles: [`
.es-title{margin:0 0 var(--rhc-space-max-sm)}
.es-list{margin:0;padding-inline-start:var(--rhc-space-max-xl)}
/* Default link color doesn't meet contrast on the error-alert's light-red surface. */
.es-list a{color:var(--rhc-color-lintblauw-700)}
`],
template: `
@switch (status()) {