Storybook Accessibility Testing
Der Befund fällt schon in der Story auf
Icon-Button und verborgene Karte: zwei Befunde je Komponente.
Story-Testlabor
Stories werden zu Prüfständen
Jede Story friert einen Zustand ein. axe prüft den gerenderten DOM, play durchläuft Verhalten und Vitest trägt den Befund bis in die CI.
Ein Befund, direkt an der Komponente
Konzeptionelle Storybook-Ansicht. Die Oberfläche zeigt den typischen Weg von der Story zum markierten Element; Bezeichnungen und Anordnung können je nach Storybook-Version variieren.
Markiertes Element<button class="icon">
Schaltflächen müssen einen wahrnehmbaren Namen haben.
aria-label="Schließen"„Incomplete“ verlangt eine manuelle Entscheidung; es ist kein bestandener Test.
Die Prüfkette hat vier getrennte Aufgaben
argsZustand aufbauenleer · offen · Fehler · deaktiviertplayVerhalten ausführenTab · Enter · Eingabe · Fokusaxe-coreDOM analysierenViolations · Passes · IncompleteVitestErgebnis weitergebenUI · CLI · CI-StatusDrei Ebenen statt eines grünen Häkchens
Namen, Rollen, ARIA-Beziehungen und viele Kontrastfehler.
play in der StoryÖffnen, tippen, tabben und den erwarteten Zustand prüfen.
Bedienlogik, verständliche Ansagen und „Incomplete“-Fälle beurteilen.
Ein fehlerfreier axe-Lauf ist ein technisches Signal. Er belegt nicht, dass die Komponente insgesamt verständlich oder in jedem Zustand bedienbar ist.
Der aktuelle kurze Setup-Pfad
npx storybook add @storybook/addon-a11y
npx storybook add @storybook/addon-vitestDer erste Befehl installiert und konfiguriert das Accessibility-Addon. Der zweite richtet bei einem Vite-basierten Storybook den Browser-Testlauf mit Vitest ein.
Fehler projektweit aktivieren
// .storybook/preview.js
const preview = {
parameters: {
a11y: {
test: 'error',
},
},
};
export default preview;error macht Verstöße zu fehlgeschlagenen Tests. todo zeigt sie lokal als Warnung, blockiert die CI aber nicht. off schaltet den automatischen Test für die Story aus.
Zustände und Tastaturweg in einer Story-Datei
Feste args geben axe reproduzierbare Zustände. Die play-Funktion prüft zusätzlich, ob der benannte Auslöser per Tastatur erreichbar ist.
- MitName: stabile DOM-Momentaufnahme für axe.
- Tastatur: Fokus und Enter-Verhalten als Interaktionstest.
- OhneName: nur als bewusste Fehler-Story mit
todo.
// IconButton.stories.js
import { expect, fn } from 'storybook/test';
import { IconButton } from './IconButton';
export default {
component: IconButton,
parameters: { a11y: { test: 'error' } },
};
export const MitName = {
args: { label: 'Schließen' },
};
export const Tastatur = {
args: { label: 'Schließen', onClick: fn() },
play: async ({ args, canvas, userEvent }) => {
const knopf = canvas.getByRole('button', {
name: 'Schließen',
});
await userEvent.tab();
await expect(knopf).toHaveFocus();
await userEvent.keyboard('{Enter}');
await expect(args.onClick).toHaveBeenCalled();
},
};
export const OhneName = {
args: { label: '' },
parameters: { a11y: { test: 'todo' } },
};So prüfen Sie es
- Öffnen Sie jede relevante Zustands-Story. Prüfen Sie im Bereich Accessibility die Gruppen Violations, Passes und Incomplete.
- Markieren Sie einen Verstoß und prüfen Sie das hervorgehobene Element im gerenderten Canvas. Korrigieren Sie die Komponente, nicht nur die Story-Dekoration.
- Führen Sie die Komponententests mit aktivierter Accessibility-Option aus. Eine Story mit
test: 'error'muss bei einem axe-Verstoß in UI und CI fehlschlagen. - Gehen Sie die Story danach mit Tab, Enter, Leertaste und einem Vorleseprogramm durch. Bearbeiten Sie alle „Incomplete“-Fälle als echte Prüfaufgaben.
Aus dem Prüfbericht
Zwei Befunde an der Komponente
Kritisch Der Icon-Button in der Story hat keinen Namen Regel button-name
Das Symbol trägt aria-hidden, also bleibt der Button namenlos. Ein aria-label an der Komponente liefert das Wort.
Zum Mitnehmen
Die Komponente, korrigiert
Ein aria-label, ein entferntes Attribut, ein strenger Testlauf.
Korrektur in 3 Schritten ansehen
Dem Icon-Button einen Namen geben
Das Symbol bleibt für Vorleseprogramme verborgen. aria-label liefert stattdessen das Wort, das den Button benennt.
KorrekturvergleichSchritt 1 · HTML Vorher
<button class="icon-button" type="button"> <svg aria-hidden="true"><use href="#icon-schliessen"></use></svg> </button>Nachher
<button class="icon-button" type="button" aria-label="Schließen"> <svg aria-hidden="true"><use href="#icon-schliessen"></use></svg> </button>Markierte Zeilen wurden geändert
So prüfen Sie es Tabben Sie in der Story auf den Button. Ein Vorleseprogramm sagt „Schließen, Schaltfläche“.
Das aria-hidden am Wrapper entfernen
aria-hidden nimmt den Bereich aus der Ausgabe, lässt den Link aber in der Tabreihenfolge. Beides zusammen widerspricht sich.
KorrekturvergleichSchritt 2 · HTML Vorher
<div class="karte" aria-hidden="true"> <a href="/details">Details ansehen</a> </div>Nachher
<div class="karte"> <a href="/details">Details ansehen</a> </div>Markierte Zeilen wurden geändert
So prüfen Sie es Tabben Sie auf den Link. Ein Vorleseprogramm nennt ihn jetzt beim Namen.
Den Befund im Testlauf festhalten
Mit der Stufe error bricht der Lauf ab, sobald eine Story einen Befund hat. So bleibt die Korrektur bestehen.
KorrekturvergleichSchritt 3 · JavaScript Vorher
export const Standard = { args: { label: '' }, };Nachher
export const Standard = { args: { label: 'Schließen' }, parameters: { a11y: { test: 'error' } }, };Markierte Zeilen wurden geändert
So prüfen Sie es Starten Sie den Testlauf. Er endet mit einem Fehler, solange ein Button namenlos ist.
