diff --git a/.agents/skills/accessibility/SKILL.md b/.agents/skills/accessibility/SKILL.md new file mode 100644 index 00000000..a91ec53a --- /dev/null +++ b/.agents/skills/accessibility/SKILL.md @@ -0,0 +1,115 @@ +--- +name: accessibility +description: >- + Guides frontend accessibility using Curve personas and WCAG-oriented rules: + semantic HTML, accessible names, keyboard access, focus, and persona-based + review. Use when writing or reviewing React, Angular, HTML, or CSS UI, or when + the user mentions a11y, accessibility, WCAG, toegankelijkheid, personas, + keyboard navigation, screenreader, or accessible names. +--- + +# Web accessibility (Curve) + +Apply this skill whenever you **write, edit, or review** UI. Do not wait for the user to mention a11y. + +Read [personas.md](personas.md) for the seven user perspectives. Read [reference.md](reference.md) for +detailed HTML, keyboard, and naming rules. + +## When to use which mode + +| Situation | Mode | +| --------- | ---- | +| Writing or editing UI | Baseline workflow (below) + relevant persona checks | +| "Review for accessibility" / PR review | **Full persona review** | +| "Review as [persona]" | **Single persona review** | +| Quick sanity check | Baseline workflow only | + +## Baseline workflow (always) + +When changing UI, run in order: + +1. **Semantics** — correct HTML element (see [reference.md](reference.md)). +2. **Names** — every control has a visible label or accessible name. +3. **Structure** — one `h1`, no skipped heading levels, landmarks present. +4. **Keyboard** — Tab reaches every control; focus is visible. +5. **Skip links** — repeated chrome can be skipped on full pages. + +Prefer native HTML before ARIA. If Curve components exist, use them instead of rebuilding primitives. + +## Persona review workflow + +Use this when reviewing a component, page, or story. + +1. Read the code (and story/demo if present). Identify interactive elements, status feedback, media, and layout constraints. +2. Walk **each persona** in [personas.md](personas.md). For each one, ask that persona's review questions against the actual markup and behaviour. +3. Map findings to severity: + - **Must fix** — blocks a persona from using the UI (no name, keyboard trap, colour-only status, hover-only content) + - **Should fix** — friction or WCAG risk (weak contrast, small targets, vague errors) + - **Note** — improvement, not a blocker +4. End with **cross-cutting fixes** — changes that help multiple personas. + +Do not answer "is this accessible?" with a single yes/no. Report concrete, verifiable findings. + +### Full review output template + +```markdown +# Accessibility review: [Component or page name] + +## Blind, screenreadergebruiker +- [Must fix] … +- [Should fix] … + +## Slechtziend, vergroting +- … + +## Kleurenblind +- … + +## Doof of slechthorend +- … + +## Beperkte motoriek +- … + +## Cognitief of neurodivergent +- … + +## Tijdelijk of situationeel +- … + +## Cross-cutting fixes +1. … +2. … +``` + +Omit empty persona sections. If a persona has no issues, write "Geen bevindingen" for that section. + +### Single persona output + +When the user names one persona, use the same severity labels but only that section plus cross-cutting fixes. + +## Good prompts (for the user) + +These produce verifiable answers: + +- "Welk element krijgt focus als dit opengaat, en wat leest een screenreader voor?" +- "Kun je de foutstatus begrijpen zonder kleur te zien?" +- "Is elke actie bereikbaar met alleen het toetsenbord?" +- "Welk native element maakt dit ARIA-attribuut overbodig?" + +Avoid accepting a bare "yes, accessible" without mechanism. + +## Limits + +This skill does not replace manual testing with VoiceOver/NVDA or `@storybook/addon-a11y`. Treat output +like a linter: fast and useful, but not a substitute for real assistive-tech checks. + +## Installation (for humans) + +| Tool | Path | +| ---- | ---- | +| Cursor | `.cursor/skills/accessibility/` (this folder) | +| Claude Code | `.claude/skills/accessibility/` | +| Other agents | `.agents/skills/accessibility/` | + +Download the full folder from Curve Storybook: **Curve → Voor developers → Je werk testen → Wanneer je gebruik maakt van AI**. diff --git a/.agents/skills/accessibility/personas.md b/.agents/skills/accessibility/personas.md new file mode 100644 index 00000000..668325f9 --- /dev/null +++ b/.agents/skills/accessibility/personas.md @@ -0,0 +1,122 @@ +# Accessibility personas (Curve) + +"Toegankelijk" gaat niet over één doelgroep. De persona's hieronder dekken de behoeften die de +WCAG-criteria daadwerkelijk sturen, en ze lopen elk op andere fouten vast. Gebruik ze om te +voorspellen welk criterium een ontwerp breekt door je voor te stellen wie er niet langs komt. + +| Persona | Hoe diegene jouw website gebruikt | Waar het misgaat | +| ---------------------------- | ------------------------------------------------------ | --------------------------------------------------------------------- | +| Blind, screenreadergebruiker | Alleen toetsenbord, luistert; navigeert via koppen en links | Naamloze knoppen, `div`-knoppen, betekenis die alleen zichtbaar is | +| Slechtziend, vergroting | 200–400% zoom, hoog contrast, grote letters | Vaste breedtes, te licht contrast, tekst in afbeeldingen | +| Kleurenblind | Ziet de opmaak, niet het kleurverschil | Status alleen in kleur, rood/groen-combinaties, ongelabelde grafieken | +| Doof of slechthorend | Leest in plaats van luistert | Video zonder ondertiteling, geluidssignalen, geen transcript | +| Beperkte motoriek | Toetsenbord, switch, spraak of oogbesturing | Kleine klikdoelen, alleen slepen, hover-menu's, korte time-outs | +| Cognitief of neurodivergent | Heeft rust, voorspelbaarheid en eenvoud nodig | Jargon, automatische beweging, tijdsdruk, vage foutmeldingen | +| Tijdelijk of situationeel | Van alles, kort en onhandig | Alles hierboven, op het slechtst denkbare moment | + +## Blind, screenreadergebruiker + +Gebruikt NVDA, JAWS, VoiceOver of TalkBack en ziet de opmaak nooit. De pagina wordt als structuur +opgenomen: een lijst met koppen, een lijst met links, landmarks, en dan pas inhoud. Visuele groepering +betekent niets als die niet in de opmaak zit. + +**Wat dit van je vraagt:** echte koppen in de juiste volgorde, één `h1`, landmarks (`main`, `nav`, +`header`) in plaats van anonieme `div`s, een toegankelijke naam op elk bedienbaar element, en +alternatieve tekst die vertelt wat een afbeelding overbrengt in plaats van wat erop staat. Een +icoonknop die wordt voorgelezen als "knop" is een doodlopende weg. + +**Review-vragen:** + +- Wat leest een screenreader voor elk interactief element? +- Is de kopstructuur een logische inhoudsopgave? +- Zit essentiële informatie alleen in visuele opmaak (kleur, positie, icoon zonder label)? + +## Slechtziend, vergroting + +Zoomt tot 200% of verder, of zet het besturingssysteem op grote letters. Bij 400% zoom op een viewport +van 1280px is jouw desktoplayout nog ongeveer 320px breed — het WCAG-criterium Reflow zegt dat de +inhoud daar moet blijven werken, in één scrollrichting, zonder dat er iets wegvalt. + +**Wat dit van je vraagt:** layouts die meebewegen in plaats van horizontaal scrollen, tekst die 200% +vergroting overleeft zonder over elkaar te vallen, contrast van minimaal 4,5:1 voor lopende tekst en +3:1 voor interface-elementen en iconen, en geen essentiële tekst die in een afbeelding zit. + +**Review-vragen:** + +- Blijft de layout bruikbaar bij 200–400% zoom? +- Is contrast voldoende voor tekst én UI-elementen? +- Val essential content weg of wordt afgesneden? + +## Kleurenblind + +Ongeveer 8% van de mannen en 0,5% van de vrouwen heeft een vorm van kleurenblindheid, meestal +rood/groen. Zij zien jouw opmaak prima; wat wegvalt is het onderscheid dat je in kleur hebt gestopt. + +**Wat dit van je vraagt:** laat kleur nooit de enige manier zijn waarop je informatie communiceert. Combineer het met een icoon, een label, +een patroon of een positie. Een invoerveld dat rood kleurt is onzichtbaar; een veld dat rood kleurt, +een waarschuwingsicoon krijgt en de zin "Vul een geldig e-mailadres in" toont, werkt voor iedereen. + +**Review-vragen:** + +- Kun je status (fout, succes, geselecteerd) begrijpen zonder kleur te zien? +- Zijn grafieken en diagrammen ook zonder kleur te onderscheiden? + +## Doof of slechthorend + +Leest in plaats van luistert. Beschrijft ook iedereen in een kantoortuin zonder koptelefoon. + +**Wat dit van je vraagt:** ondertiteling bij alles waarin gesproken wordt, transcripten bij audio, en geen +statuswijziging die alleen met geluid wordt aangekondigd. + +**Review-vragen:** + +- Is alle audio/video-inhoud ook leesbaar? +- Worden statuswijzigingen ook visueel of tekstueel aangekondigd? + +## Beperkte motoriek + +Een brede groep: tremor, RSI, bediening met één hand, een switch, spraakbesturing, oogbesturing. Wat ze +delen is dat nauwkeurig aanwijzen duur of onmogelijk is. + +**Wat dit van je vraagt:** alles moet bereikbaar en bedienbaar zijn met het toetsenbord, in een volgorde +die overeenkomt met de opmaak, met focus die altijd zichtbaar is. Klikdoelen zijn minimaal 24×24 +CSS-pixels (44×44 is comfortabel). Alles wat je met slepen kunt doen, moet ook met één klik of met het +toetsenbord kunnen. Inhoud die alleen bij hover verschijnt is onbereikbaar — koppel die ook aan focus, +en zorg dat je hem kunt wegklikken zonder de muis te verplaatsen. + +**Review-vragen:** + +- Is elke actie bereikbaar met Tab/Enter/Spatie? +- Zijn klikdoelen groot genoeg? +- Zijn er hover-only of drag-only interacties? + +## Cognitief of neurodivergent + +Dyslexie, ADHD, autisme, verschillen in geheugen of verwerkingssnelheid, angst — en iedereen onder +druk. Dit is de grootste groep en de groep die het minst geholpen wordt door automatische controles, +omdat niets ervan in de opmaak te zien is. + +**Wat dit van je vraagt:** gewone taal in plaats of slimme taal, navigatie en knoppen die steeds op +dezelfde plek staan, geen onverwachte beweging of automatisch afspelen, respect voor +`prefers-reduced-motion`, ruime of verlengbare tijdslimieten, foutmeldingen die het probleem én de +oplossing noemen, en niets dat afhangt van wat iemand zich uit een vorige stap herinnert. + +**Review-vragen:** + +- Zijn foutmeldingen concreet en oplossingsgericht? +- Is de flow voorspelbaar, zonder verrassende animaties of time-outs? +- Is de taal eenvoudig genoeg? + +## Tijdelijk of situationeel + +Een gebroken arm, een ooginfectie, een kind op de arm, een gebarsten scherm, fel zonlicht, een tunnel. +Niemand hiervan noemt zichzelf beperkt, en ze lopen allemaal tegen dezelfde drempels aan. + +Dit is het curb-cut-effect: ondertiteling wordt gebruikt in stille kantoren, sneltoetsen door ervaren +gebruikers, hoog contrast door mensen buiten. Werk dat je voor de persona's hierboven doet, is zelden +alleen voor hen. + +**Review-vragen:** + +- Welke persona's raken het hardst getroffen door dit ontwerp? +- Lost een fix voor één persona vaak meerdere problemen tegelijk op? diff --git a/.agents/skills/accessibility/reference.md b/.agents/skills/accessibility/reference.md new file mode 100644 index 00000000..96b7cf75 --- /dev/null +++ b/.agents/skills/accessibility/reference.md @@ -0,0 +1,131 @@ +# Web accessibility reference + +Detailed rules for semantic HTML, keyboard access, and accessible names. The agent applies these +when writing or reviewing UI (React, Angular, HTML, CSS). + +Prefer native HTML before ARIA. Do not "fix" accessibility with `role="button"` + `tabindex="0"` + +a click handler on a `div` when a native ` + + + ); +} +``` + +**Angular:** + +```ts +import { Component } from '@angular/core'; +import { HlmButton } from '@surfnet/curve-angular'; + +@Component({ + selector: 'app-voorbeeld', + imports: [HlmButton], + template: ` + + + `, +}) +export class VoorbeeldComponent {} +``` + +De knop heeft zes varianten — `default`, `outline`, `secondary`, `ghost`, `destructive` en `link` — en +acht maten. Laat je `variant` weg, dan krijg je `default`. + +Twee dingen om te weten over Angular: componenten zijn _standalone_, dus je zet ze in `imports` van je +eigen component in plaats van in een module. En de meeste Curve-componenten zijn directives — je zet +`hlmBtn` op een echt ` +``` + +Houd je daarbij aan twee regels: + +- **Gebruik tokens, geen vaste kleurcodes.** Schrijf `bg-primary` of `text-muted-foreground` in plaats + van `bg-[#1a73e8]`. Alleen dan blijft je werk goed in alle thema's. +- **Vecht niet met een component.** Moet je met `!important` of hele hoge specificiteit werken om iets + voor elkaar te krijgen, dan is dat een signaal. Vaak bestaat er een variant voor, en anders is het + een goed onderwerp voor een issue. + +## Stap 7 — Zo vind je je weg in deze Storybook + +- **Curve** — documentatie over het Curve design system. +- Verder in deze sectie — wat je zelf nog moet doen om toegankelijk te bouwen. +- **Components** — elk component, met een voorbeeld per variant en state. +- Het tabblad **Docs** van een component — alle eigenschappen met hun standaardwaarden. +- **Foundations → Design Tokens** — welke kleuren, tekststijlen en maten er zijn. +- De **Framework**-schakelaar in de werkbalk — springt naar hetzelfde component in het andere + framework. + +## Stap 8 — Mis je iets, of klopt iets niet? + +Meld het, ook als je het zelf omzeilt: iemand anders loopt tegen hetzelfde aan. Zet erbij welke versie je gebruikt, welk framework, en wat je verwachtte. Heb je github? Maak dan een issue aan op de [Curve GitHub repository](https://github.com/SURFnet/DesignSystem/issues). Bedankt! + +Wil je zelf een component toevoegen, doe dat dan niet met de hand: er is een generator per framework +en een vaste plek in de mappenstructuur. Vraag ernaar voordat je begint, dan hoeft het achteraf niet +opnieuw. diff --git a/packages/storybook-config/docs/curve/03-voor-developers/03-robuust-bouwen.mdx b/packages/storybook-config/docs/curve/03-voor-developers/03-robuust-bouwen.mdx new file mode 100644 index 00000000..5c50360f --- /dev/null +++ b/packages/storybook-config/docs/curve/03-voor-developers/03-robuust-bouwen.mdx @@ -0,0 +1,124 @@ +import { Meta } from '@storybook/addon-docs/blocks'; + + + +# Robuust bouwen + +## Persona's + +Dit is een lijst voorbeelden van verschillende beperkingen die iemand kan hebben, en hoe dat beinvloedt hoe ze je website gebruiken. Het is geen volledige lijst. Ook betekent het niet dat iemand met bijvoorbeeld blindheid een toetsenbord gebruikt. Mensen zijn allemaal verschillend! + +Elk voorbeeld onder **Waar het misgaat** heeft een eigen pagina onder +[Wat vaak mis gaat](?path=/docs/curve-voor-developers-wat-vaak-mis-gaat--naamloze-knoppen): +wat er gebeurt, en hoe je het oplost. + +| Persona | Hoe diegene jouw website gebruikt | Waar het misgaat | +| ------------------------------------------------------------ | ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| [Blind, screenreadergebruiker](#blind-screenreadergebruiker) | Alleen toetsenbord, luistert; navigeert via koppen en links | [Naamloze knoppen](?path=/docs/curve-voor-developers-wat-vaak-mis-gaat--naamloze-knoppen), [Teveel ARIA](?path=/docs/curve-voor-developers-wat-vaak-mis-gaat--teveel-aria), [Verkeerde ARIA](?path=/docs/curve-voor-developers-wat-vaak-mis-gaat--verkeerde-aria), [ontbrekende pagina-structuur](?path=/docs/curve-voor-developers-wat-vaak-mis-gaat--ontbrekende-pagina-structuur), [ontbreken van unieke pagina-titel](?path=/docs/curve-voor-developers-wat-vaak-mis-gaat--ontbreken-van-unieke-pagina-titel), [tabellen zonder koppen](?path=/docs/curve-voor-developers-wat-vaak-mis-gaat--tabellen-zonder-koppen), [afbeeldingen zonder beschrijving](?path=/docs/curve-voor-developers-wat-vaak-mis-gaat--afbeeldingen-zonder-beschrijving), [slechte alt-tekst](?path=/docs/curve-voor-developers-wat-vaak-mis-gaat--slechte-alt-tekst), [ontbrekende bijschriften](?path=/docs/curve-voor-developers-wat-vaak-mis-gaat--ontbrekende-bijschriften), [video die automatisch afspeelt](?path=/docs/curve-voor-developers-wat-vaak-mis-gaat--video-die-automatisch-afspeelt) | +| [Slechtziend, vergroting](#slechtziend-vergroting) | 200–400% zoom, hoog contrast, grote letters | [Vaste breedtes](?path=/docs/curve-voor-developers-wat-vaak-mis-gaat--vaste-breedtes), [te licht contrast](?path=/docs/curve-voor-developers-wat-vaak-mis-gaat--te-licht-contrast), [tekst in afbeeldingen](?path=/docs/curve-voor-developers-wat-vaak-mis-gaat--tekst-in-afbeeldingen), [taalwissels zonder markering](?path=/docs/curve-voor-developers-wat-vaak-mis-gaat--taalwissels-zonder-markering) | +| [Kleurenblind](#kleurenblind) | Ziet de opmaak, niet het kleurverschil | [Status alleen in kleur](?path=/docs/curve-voor-developers-wat-vaak-mis-gaat--status-alleen-in-kleur), [rood/groen-combinaties](?path=/docs/curve-voor-developers-wat-vaak-mis-gaat--rood-groen-combinaties), [ongelabelde grafieken](?path=/docs/curve-voor-developers-wat-vaak-mis-gaat--ongelabelde-grafieken) | +| [Doof of slechthorend](#doof-of-slechthorend) | Leest in plaats van luistert | [Video zonder ondertiteling](?path=/docs/curve-voor-developers-wat-vaak-mis-gaat--video-zonder-ondertiteling), [geen transcript](?path=/docs/curve-voor-developers-wat-vaak-mis-gaat--geen-transcript) | +| [Beperkte motoriek](#beperkte-motoriek) | Toetsenbord, switch, spraak of oogbesturing | [Kleine klikdoelen](?path=/docs/curve-voor-developers-wat-vaak-mis-gaat--kleine-klikdoelen), [alleen slepen](?path=/docs/curve-voor-developers-wat-vaak-mis-gaat--alleen-slepen), [hover-menu's](?path=/docs/curve-voor-developers-wat-vaak-mis-gaat--hover-menu-s), [korte time-outs](?path=/docs/curve-voor-developers-wat-vaak-mis-gaat--korte-time-outs) | +| [Cognitief of neurodivergent](#cognitief-of-neurodivergent) | Heeft rust, voorspelbaarheid en eenvoud nodig | [automatische beweging](?path=/docs/curve-voor-developers-wat-vaak-mis-gaat--automatische-beweging), [tijdsdruk](?path=/docs/curve-voor-developers-wat-vaak-mis-gaat--tijdsdruk), [vage foutmeldingen](?path=/docs/curve-voor-developers-wat-vaak-mis-gaat--vage-foutmeldingen), [onduidelijke validatie](?path=/docs/curve-voor-developers-wat-vaak-mis-gaat--onduidelijke-validatie) | +| [Tijdelijk of situationeel](#tijdelijk-of-situationeel) | Van alles, kort en onhandig | [Alles hierboven, op het slechtst denkbare moment](?path=/docs/curve-voor-developers-wat-vaak-mis-gaat--op-het-slechtst-denkbare-moment) | + +## Blind, screenreadergebruiker + +Gebruikt NVDA, JAWS, VoiceOver of TalkBack en ziet de opmaak nooit. De pagina wordt als structuur +opgenomen: een lijst met koppen, een lijst met links, landmarks, en dan pas inhoud. Visuele groepering +betekent niets als die niet in de opmaak zit. + +Wat dit van je vraagt: echte koppen in de juiste volgorde, één `h1`, landmarks (`main`, `nav`, +`header`) in plaats van anonieme `div`s, een toegankelijke naam op elk bedienbaar element, en +alternatieve tekst die vertelt wat een afbeelding overbrengt in plaats van wat erop staat. Een +icoonknop die wordt voorgelezen als "knop" is een doodlopende weg. Een `div` met een klikafhandelaar +is geen knop: dat staat bij +[Teveel ARIA](?path=/docs/curve-voor-developers-wat-vaak-mis-gaat--teveel-aria). +Hoe je namen, status en live regions zet, bij +[Verkeerde ARIA](?path=/docs/curve-voor-developers-wat-vaak-mis-gaat--verkeerde-aria). +Hoe je alt-tekst schrijft, bij +[Slechte alt-tekst](?path=/docs/curve-voor-developers-wat-vaak-mis-gaat--slechte-alt-tekst). +Een bijschrift is extra uitleg voor iedereen, geen vervanging van die alt-tekst: zie +[Ontbrekende bijschriften](?path=/docs/curve-voor-developers-wat-vaak-mis-gaat--ontbrekende-bijschriften). +De [paginatitel](?path=/docs/curve-voor-developers-wat-vaak-mis-gaat--ontbreken-van-unieke-pagina-titel) +is het eerste dat wordt voorgelezen. +[Tabellen](?path=/docs/curve-voor-developers-wat-vaak-mis-gaat--tabellen-zonder-koppen) +horen kopcellen te hebben, en zijn geen layoutgereedschap. + + + +## Slechtziend, vergroting + +Zoomt tot 200% of verder, of zet het besturingssysteem op grote letters. Bij 400% zoom op een viewport +van 1280px is jouw desktoplayout nog ongeveer 320px breed: het WCAG-criterium Reflow zegt dat de +inhoud daar moet blijven werken, in één scrollrichting, zonder dat er iets wegvalt. + +Wat dit van je vraagt: layouts die meebewegen in plaats van horizontaal scrollen, tekst die 200% +vergroting overleeft zonder over elkaar te vallen, contrast van minimaal 4,5:1 voor lopende tekst en +3:1 voor interface-elementen en iconen, en geen essentiële tekst die in een afbeelding zit. Hoe je +zoom en informatieve afbeeldingen aanpakt, staat bij +[Touch en vergroting](?path=/docs/curve-voor-designers--touch-en-vergroting). +Zonder `lang` is vergroting mét voorlezen onverstaanbaar: zie +[Taalwissels zonder markering](?path=/docs/curve-voor-developers-wat-vaak-mis-gaat--taalwissels-zonder-markering). + +## Kleurenblind + +Ongeveer 8% van de mannen en 0,5% van de vrouwen heeft een vorm van kleurenblindheid, meestal +rood/groen. Zij zien jouw opmaak prima; wat wegvalt is het onderscheid dat je in kleur hebt gestopt. + +Wat dit van je vraagt: laat kleur nooit de enige manier zijn waarop je informatie communiceert. Combineer het met een icoon, een label, +een patroon of een positie. Een invoerveld dat rood kleurt is onzichtbaar; een veld dat rood kleurt, +een waarschuwingsicoon krijgt en de zin "Vul een geldig e-mailadres in" toont, werkt voor iedereen. +Hoe je die melding koppelt, staat bij +[Onduidelijke validatie](?path=/docs/curve-voor-developers-wat-vaak-mis-gaat--onduidelijke-validatie). + +## Doof of slechthorend + +Leest in plaats van luistert. Beschrijft ook iedereen in een kantoortuin zonder koptelefoon. + +Wat dit van je vraagt: ondertiteling bij alles waarin gesproken wordt, transcripten bij audio, en geen +statuswijziging die alleen met geluid wordt aangekondigd. Uitwerking staat bij +[Video en audio](?path=/docs/curve-voor-designers--video-en-audio). + +## Beperkte motoriek + +Een brede groep: tremor, RSI, bediening met één hand, een switch, spraakbesturing, oogbesturing. Wat ze +delen is dat nauwkeurig aanwijzen duur of onmogelijk is. + +Wat dit van je vraagt: alles moet bereikbaar en bedienbaar zijn met het toetsenbord, in een volgorde +die overeenkomt met de opmaak, met focus die altijd zichtbaar is. Klikdoelen zijn minimaal 24×24 +CSS-pixels (44×44 is comfortabel). Alles wat je met slepen kunt doen, moet ook met één klik of met het +toetsenbord kunnen. Inhoud die alleen bij hover verschijnt is onbereikbaar: koppel die ook aan focus, +en zorg dat je hem kunt wegklikken zonder de muis te verplaatsen. Maten, telefoon en gebaren staan bij +[Touch en vergroting](?path=/docs/curve-voor-designers--touch-en-vergroting). + +## Cognitief of neurodivergent + +Dyslexie, ADHD, autisme, verschillen in geheugen of verwerkingssnelheid, angst: en iedereen onder +druk. Dit is de grootste groep en de groep die het minst geholpen wordt door automatische controles, +omdat niets ervan in de opmaak te zien is. + +Wat dit van je vraagt: gewone taal in plaats van slimme taal, navigatie en knoppen die steeds op +dezelfde plek staan, geen onverwachte beweging of automatisch afspelen, respect voor +`prefers-reduced-motion`, ruime of verlengbare tijdslimieten, foutmeldingen die het probleem én de +oplossing noemen, en niets dat afhangt van wat iemand zich uit een vorige stap herinnert. Hoe je die +teksten schrijft, staat bij +[Microcopy](?path=/docs/curve-voor-designers--microcopy). +Hoe je fouten koppelt en aankondigt, bij +[Onduidelijke validatie](?path=/docs/curve-voor-developers-wat-vaak-mis-gaat--onduidelijke-validatie). + +## Tijdelijk of situationeel + +Een gebroken arm, een ooginfectie, een kind op de arm, een gebarsten scherm, fel zonlicht, een tunnel. +Niemand hiervan noemt zichzelf beperkt, en ze lopen allemaal tegen dezelfde drempels aan. + +Dit is het curb-cut-effect: ondertiteling wordt gebruikt in stille kantoren, sneltoetsen door ervaren +gebruikers, hoog contrast door mensen buiten. Werk dat je voor de persona's hierboven doet, is zelden +alleen voor hen. Zie +[Op het slechtst denkbare moment](?path=/docs/curve-voor-developers-wat-vaak-mis-gaat--op-het-slechtst-denkbare-moment). + +## Gebruik met een coding agent + +Deze persona's zitten ook in de [accessibility skill voor AI](?path=/docs/curve-voor-developers-je-werk-testen--wanneer-je-gebruik-maakt-van-ai). +Download de skill en vraag je agent om UI te beoordelen vanuit elk perspectief: bijvoorbeeld: "Wat zou een +screenreadergebruiker missen in dit component?" diff --git a/packages/storybook-config/docs/curve/03-voor-developers/04-je-werk-testen/01-overzicht.mdx b/packages/storybook-config/docs/curve/03-voor-developers/04-je-werk-testen/01-overzicht.mdx new file mode 100644 index 00000000..767f8abf --- /dev/null +++ b/packages/storybook-config/docs/curve/03-voor-developers/04-je-werk-testen/01-overzicht.mdx @@ -0,0 +1,40 @@ +import { Meta } from '@storybook/addon-docs/blocks'; + + + +# Je werk testen + +Eén tool dekt toegankelijkheid niet af. Automatische controle vindt ongeveer 40% van de echte WCAG-fouten. In dat deel dat wordt gemist zitten de meeste problemen die iemand daadwerkelijk in de weg zitten. Een pagina kan nul AXE-meldingen geven of een perfecte Lighthouse score, en toch onbruikbaar zijn. Maar daarom blijft het ook mensenwerk! Maar hoe fijn is het als het laaghangend fruit vroeg opgespoord wordt, zodat je je de rest van de tijd kunt focussen op het maken van een goede gebruiksvriendelijke website? + +## Automatische controle + +| Wanneer | Hulpmiddel | Wat het opmerkt | +| -------------------------------------- | ------------------------------------------------------------------------- | --------------------------------------------------------------------------------- | +| Tijdens het schrijven en reviewen | Agent skill (voor wie LLM's gebruikt) | Verkeerd element, ontbrekende naam, overgeslagen koppen, weggehaalde focusstijlen | +| Bij opslaan en in pull requests | Linter | Ontbrekende labels en alt-teksten, klikafhandelaars op niet-knoppen, ARIA-fouten | +| Bij elke pull request | Geautomatiseerde tests + CI voor wie CI gebruikt | Terugval op belangrijke flows (formulieren, navigatie, dialogen) | +| Vlak voor je een nieuw scherm oplevert | Toetsenbord en screenreader voor wie toetsenbord en screenreader gebruikt | Focusvolgorde, skiplinks, koplogica, echt gebruik: dingen die axe niet ziet | + +## Waar je begint als je nog geen werkwijze hebt + +1. Installeer + [de agent skill](?path=/docs/curve-voor-developers-je-werk-testen--wanneer-je-gebruik-maakt-van-ai) zodat nieuwe + code dichter bij goed begint. +2. Zet de toegankelijkheidsregels van je linter aan. + [Axe accessibility linter for Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=deque-systems.vscode-axe-linter) + [React's accessibility code linter](https://www.24a11y.com/2017/reacts-accessibility-code-linter/) + [Jetbrains IDE's Accessibility Linter](https://plugins.jetbrains.com/plugin/19498-accessibility-linter) + [How to lint HTML using CSS](https://dev.to/believer/how-to-lint-html-using-css-5dc) +3. [Loop de feature die je bouwt één keer met het toetsenbord door.](?path=/docs/curve-voor-developers-je-werk-testen--handmatig-testen) +4. Hang axe pas daarna in CI, zodat je niet begint met een muur aan bestaande meldingen. + [Axe accessibility linter for GitHub Actions](https://github.com/marketplace/axe-linter) + [AccessLint](https://accesslint.com/) + [accessibility-check](https://github.com/GoogleChrome/accessibility-check) + [Using GitHub Actions to automate accessibility tests](https://bolonio.medium.com/automating-the-accessibility-tests-of-your-source-code-with-github-actions-63590cdc6860#:~:text=Using%20GitHub%20Actions%20to%20automate%20accessibility%20tests&text=The%20first%20thing%20is%20to,main%20branch%20has%20that%20name) + +Allerlei hulpmiddelen tegelijk invoeren op een bestaand product levert een lijst op die niemand leest. In deze volgorde toevoegen betekent dat elke nieuwe pull request iets beter is dan de vorige. + +## Tips + +- **Behandel meldingen als bugs, niet als ruis.** Een toegankelijkheidspaneel dat altijd rood staat, leert het team om het te negeren. Dat is erger dan het niet hebben. Komt het team er niet goed uit? Neem dan contact op met het toegankelijkheidsteam! +- **Laat de build niet struikelen over je bestaande achterstand.** Laat hem falen op nieuwe fouten in de code die wordt aangeraakt, en houd bekende problemen apart bij. Een geblokkeerde pipeline die iedereen omzeilt, beschermt niemand. diff --git a/packages/storybook-config/docs/curve/03-voor-developers/04-je-werk-testen/02-handmatig-testen.mdx b/packages/storybook-config/docs/curve/03-voor-developers/04-je-werk-testen/02-handmatig-testen.mdx new file mode 100644 index 00000000..5fbcc3da --- /dev/null +++ b/packages/storybook-config/docs/curve/03-voor-developers/04-je-werk-testen/02-handmatig-testen.mdx @@ -0,0 +1,113 @@ +import { Meta } from '@storybook/addon-docs/blocks'; + + + +# Handmatig testen + +axe en linters weten niet of een kopstructuur ergens op slaat, of iets een link had moeten zijn, of de +tabvolgorde overeenkomt met wat je ziet. Loop een scherm daarom zelf na nadat je het gebouwd hebt. De +hele ronde hieronder duurt ongeveer tien minuten en vraagt geen software die je nog niet hebt. + +## De toetsenbordronde + +Laat de muis los. Klik één keer in de adresbalk en druk op Tab. + +- Elk bedienbaar element is bereikbaar, en verder niets. +- De volgorde volgt de opmaak. Springt de focus van de header naar een link in de footer en weer terug, + dan lopen de DOM-volgorde en de visuele volgorde uiteen. +- De focus is **altijd zichtbaar**. Raak jij het spoor kwijt, dan iedereen. +- Shift + Tab loopt dezelfde route terug. +- Enter activeert links en knoppen; Spatie activeert knoppen en schakelaars. +- Binnen een samengesteld component: tabs, menu, keuzelijst, radiogroep: verplaatsen de pijltoetsen de + selectie en verlaat Tab het geheel. Eén stop voor het hele component, niet één per item. +- Esc sluit elke dialoog, popover of menu, en de focus keert terug naar het element dat + het opende. +- Je kunt nergens vast komen te zitten. Blijft Tab eindeloos rondgaan in iets dat geen modale + dialoog is, dan heb je een focusval. +- De [skiplink](?path=/docs/curve-voor-developers-wat-vaak-mis-gaat--ontbrekende-skiplinks) verschijnt bij de eerste + Tab en verplaatst de focus daadwerkelijk naar de hoofdinhoud. + +## Zoomen en meebewegen + +Zie [Touch en vergroting](?path=/docs/curve-voor-designers--touch-en-vergroting) +voor klikdoelen, telefoon en inzoomen op een afbeelding. + +- Zoom naar **200%**. Niets overlapt, niets valt weg, geen tekst wordt onleesbaar. +- Zoom naar **400%** (of maak het venster 320px smal). De opmaak vouwt terug naar één kolom en scrollt + alleen verticaal. Horizontaal scrollen is hier een Reflow-fout. +- Vergroot alleen de tekst (Firefox doet dat netjes). Containers met een vaste hoogte die hun tekst + afknippen, vallen meteen op. + +## Structuur en namen + +Open DevTools → **Elements** → het paneel **Accessibility**, of gebruik een browserextensie die de +structuur toont. [HeadingsMap voor Chrome](https://chromewebstore.google.com/detail/headingsmap/flbjommegcjonpdhlhhdbkfpafnacnmjoh?hl=en) of [HeadingsMap voor Firefox](https://addons.mozilla.org/nl/firefox/addon/headingsmap/), of [HeadingsMap voor Edge](https://microsoftedge.microsoft.com/addons/detail/headingsmap/bokekiiaddinealohkmhjcgfanndmcgo). + + + + +
+
Koppen
+
+ Precies één h1, geen overgeslagen niveaus, en als je alleen de koppen leest krijg + je een inhoudsopgave die klopt. Een kopniveau is structuur, nooit een keuze voor lettergrootte. +
+
Toegankelijke namen
+
+ Elk invoerveld, elke knop en elke link heeft er één. Een placeholder is geen naam: die verdwijnt + zodra iemand begint te typen. Een icoonknop heeft een label nodig. Zes keer "Lees meer" op één + pagina zegt een screenreadergebruiker niets. Hoe je die teksten schrijft, staat bij{' '} + Microcopy. +
+
Landmarks
+
+ header, nav, main en footer bestaan, en er + is precies één main. +
+
Afbeeldingen
+
+ Decoratieve hebben alt="" zodat ze worden overgeslagen; betekenisvolle beschrijven + wat ze overbrengen, niet hoe ze eruitzien. Voorbeelden staan bij{' '} + Slechte alt-tekst. +
+
+ +## Kleur en beweging + +- Controleer het contrast van tekst én interface-elementen: 4,5:1 voor lopende tekst, 3:1 voor grote + tekst, iconen en randen. Elke kleurkiezer in DevTools laat dit zien. +- Maak een schermafbeelding en bekijk hem in grijstinten. Alles wat je dan niet meer kunt onderscheiden, + leunde op kleur alleen. +- Zet **Verminder beweging** aan in je systeeminstellingen en herlaad. Animaties horen korter te worden + of te stoppen, niet gewoon door te gaan. + +## Formulieren in het bijzonder + +Bij formulieren kost een toegankelijkheidsfout echt geld, dus loop die een tweede keer na. + +- Klikken op het label zet de focus in het veld (dat bewijst dat het label gekoppeld is en niet alleen + ernaast staat). +- Fouten worden voorgelezen, niet alleen gekleurd. Na een mislukte verzending gaat de focus naar een + zinnige plek en is de melding bereikbaar vanaf het veld waar hij bij hoort. +- De fouttekst zegt wat je moet doen: "Vul een datum in als DD-MM-JJJJ", niet "Ongeldige invoer". +- Verplichte velden zijn in tekst gemarkeerd, niet met kleur of een onverklaarde asterisk. +- Niets hangt af van hoveren, en er gaat niets verloren als iemand er twintig minuten over doet. + +## Een steekproef met een screenreader + +Je hoeft er niet vloeiend in te zijn. Vijf minuten luisteren zegt meer dan een uur opmaak lezen, omdat +je hoort wat de browser werkelijk doorgeeft in plaats van wat jij bedoelde. + +| Screenreader | Starten | Basis | +| ---------------------- | ------------------------------------------- | ------------------------------------------------------------------------------------------------------ | +| VoiceOver (macOS) | Cmd + F5 | Ctrl+Option+pijltjes om te lezen, +U voor de rotor | +| NVDA (Windows, gratis) | Ctrl+Alt+N | Pijltjes om te lezen, H voor koppen, Insert+F7 voor de elementenlijst | +| TalkBack (Android) | Instellingen voor toegankelijkheid | Veeg naar rechts om verder te gaan, dubbeltik om te activeren | + +Waar je op let: noemt elk element een naam, een rol en zijn status ("Filters, knop, ingeklapt")? Komt de +koppenlijst overeen met de pagina? Wordt er bij het openen van een dialoog gezegd dat het een dialoog is, +en gaat de focus naar binnen? Word je op de hoogte gebracht als er iets verandert zonder dat de pagina +herlaadt? + +Zet hem uit met dezelfde toetsencombinatie. Doe dit één keer per nieuw scherm en je vindt dingen die geen +enkele tool meldt. diff --git a/packages/storybook-config/docs/curve/03-voor-developers/04-je-werk-testen/03-geautomatiseerd-testen.mdx b/packages/storybook-config/docs/curve/03-voor-developers/04-je-werk-testen/03-geautomatiseerd-testen.mdx new file mode 100644 index 00000000..d0da46b5 --- /dev/null +++ b/packages/storybook-config/docs/curve/03-voor-developers/04-je-werk-testen/03-geautomatiseerd-testen.mdx @@ -0,0 +1,148 @@ +import { Meta } from '@storybook/addon-docs/blocks'; + + + +# Geautomatiseerd testen + +Automatisering bestaat om te voorkomen dat je dezelfde fout steeds opnieuw ontdekt. Het vertelt je niet +of je interface ergens op slaat, maar het vindt wél elke keer, op elke branch en gratis het ontbrekende +label, de tekst met 3:1 contrast en de dubbele `id`. + +Vier lagen, van goedkoop naar duur. + +## 1. Linten tijdens het typen + +Een linter vangt een hele categorie fouten op bij de cursor, nog voordat er een browser aan te pas komt. +Zet de regelset aan die bij jouw templatetaal hoort, en schakel regels niet uit zonder een benoemde, +beoordeelde uitzondering. + +
+
React / JSX
+
+ eslint-plugin-jsx-a11y,{' '} + recommended of strict. +
+
Angular
+
+ De templateregels van{' '} + angular-eslint ( + @angular-eslint/template-accessibility-*). +
+
Editor
+
+ De axe Accessibility Linter-extensie voor VS Code / Cursor markeert problemen in HTML en JSX + terwijl je typt. +
+
+ +Linters zien alleen statische opmaak, dus ze kunnen niet weten dat bij `role="tab"` het bijbehorende +`tabpanel` ontbreekt. Het blijft het waardevolste uur dat je eraan besteedt. + +## 2. De Storybook-addon voor toegankelijkheid + +Beide Curve-Storybooks bevatten +[`@storybook/addon-a11y`](https://storybook.js.org/docs/writing-tests/accessibility-testing), die +axe-core loslaat op de weergegeven story. Open het paneel **Accessibility** in de addonbalk terwijl je +een component bekijkt. + +Dit is de beste plek om contrast- en naamgevingsproblemen te vinden, omdat een story het component +isoleert van de ruis van een volledige pagina. Projecten die Curve gebruiken, doen er goed aan dezelfde +addon in hun eigen Storybook te zetten. + +Een component los bekijken legt bovendien iets bloot dat een volledige pagina verbergt: een component +dat alleen toegankelijk is dankzij opmaak die zijn ouder toevallig meelevert. + +## 3. Component- en end-to-endtests + +Laat axe los op weergegeven UI in je tests. Probeer niet elke pixel van de applicatie te scannen: dek de +routes af die ertoe doen: inloggen, de belangrijkste formulieren, navigatie, en elke dialoog of overlay. + +
+
Componenttests
+
+ jest-axe of vitest-axe op een + weergegeven component. +
+
End-to-end
+
+ + @axe-core/playwright + {' '} + of cypress-axe op de belangrijkste gebruikersroutes. +
+
Storybook
+
+ De test runner kan de a11y-controles voor elke story in CI uitvoeren, wat je met nauwelijks + schrijfwerk brede dekking oplevert. +
+
+ +Test op meer dan axe wanneer het gedrag specifiek is. axe kan niet vaststellen dat de focus in de dialoog +belandde, dat Esc hem sloot en dat de focus terugkeerde naar de knop: een test wel: + +```ts +await userEvent.click(screen.getByRole('button', { name: 'Instellingen openen' })); +const dialog = screen.getByRole('dialog', { name: 'Instellingen' }); +expect(dialog).toContainElement(document.activeElement); + +await userEvent.keyboard('{Escape}'); +expect(dialog).not.toBeInTheDocument(); +expect(screen.getByRole('button', { name: 'Instellingen openen' })).toHaveFocus(); +``` + +Zoeken op rol en toegankelijke naam, zoals hierboven, is zelf al een toegankelijkheidstest: kan +`getByRole('button', { name: ... })` jouw knop niet vinden, dan een screenreader ook niet. + +## 4. Continuous integration + +Controles die alleen lokaal draaien, worden overgeslagen zodra de druk oploopt. Zet een dunne, betrouwbare +selectie op elke pull request en laat de tragere scans op `main` of 's nachts draaien. + +
+
Elke pull request
+
Linten inclusief a11y-regels, plus unittests met axe-asserties.
+
Een korte Playwright- of Cypress-run met axe op de belangrijkste routes.
+
+ 's Nachts of op main +
+
+ De toegankelijkheidscategorie van{' '} + Lighthouse CI,{' '} + pa11y-ci, of een volledige run van de Storybook + test runner. +
+
+ +Laat de build falen op nieuwe fouten in de code die wordt aangeraakt. Houd bekende problemen bij als +issues met een eigenaar, niet als een permanent rode pipeline die iedereen heeft leren negeren. + +## Wat hier allemaal niet uit komt + +Alles wat een afweging vraagt: of de kopstructuur een verhaal vertelt, of iets een link had moeten zijn, +of de tabvolgorde het ontwerp volgt, of de foutmelding helpt, of de flow werkt met een screenreader. +Automatisering verkleint de handmatige ronde: zie +[Handmatig testen](?path=/docs/curve-voor-developers-je-werk-testen--handmatig-testen): maar +schaft hem nooit af. + + +## Gereedschap + +- [axe DevTools](https://www.deque.com/axe/devtools/): browserextensie; dezelfde motor als de + Storybook-addon en de CI-packages. +- [Accessibility Insights](https://accessibilityinsights.io/): begeleide handmatige controles, met een + visualisatie van de tabvolgorde die focusproblemen meteen zichtbaar maakt. +- [WAVE](https://wave.webaim.org/extension/): zet de bevindingen op de pagina zelf; handig om iemand + zonder technische achtergrond te laten zien wat er mis is. +- [Colour Contrast Analyser](https://www.tpgi.com/color-contrast-checker/): om een ontwerp te + controleren voordat het gebouwd wordt. +- [NVDA](https://www.nvaccess.org/download/): gratis screenreader voor Windows; na JAWS de meest + gebruikte. +- [VoiceOver-handleiding (WebAIM)](https://webaim.org/articles/voiceover/): hoe je de screenreader + bedient die al op je Mac staat. + +## Testen en CI + +- [axe-core](https://github.com/dequelabs/axe-core): de regelmotor, inclusief welke regels bestaan en wat + ze niet kunnen zien. +- [WebAIM Million](https://webaim.org/projects/million/): het jaarlijkse onderzoek naar een miljoen + homepages. Ontnuchterend, en bruikbaar als je moet onderbouwen waarom hier tijd naartoe gaat. diff --git a/packages/storybook-config/docs/curve/03-voor-developers/04-je-werk-testen/04-wanneer-je-gebruik-maakt-van-ai.mdx b/packages/storybook-config/docs/curve/03-voor-developers/04-je-werk-testen/04-wanneer-je-gebruik-maakt-van-ai.mdx new file mode 100644 index 00000000..8451f2b8 --- /dev/null +++ b/packages/storybook-config/docs/curve/03-voor-developers/04-je-werk-testen/04-wanneer-je-gebruik-maakt-van-ai.mdx @@ -0,0 +1,85 @@ +import { Meta } from '@storybook/addon-docs/blocks'; + + + +# Wanneer je gebruik maakt van AI + +Coding agents produceren opmaak die er goed uitziet en verkeerd wordt voorgelezen: een `div` met een +klikafhandelaar in plaats van een knop, een placeholder in plaats van een label, `aria-label` +uitgestrooid over elementen die helemaal geen rol hebben om te benoemen. De code compileert, rendert en +komt door de review, want het gebrek is onzichtbaar totdat iemand er met een toetsenbord of een +screenreader langskomt. + +De goedkoopste oplossing is de agent de regels vooraf meegeven. Feedback over toegankelijkheid op het +moment dat de code geschreven wordt kost een zin; dezelfde feedback in een pull request kost een +herschrijving. + +## De accessibility skill + +Een map met markdown-bestanden die je in Cursor, Claude Code of een andere agent zet. De skill leert de +agent semantische HTML, toegankelijke namen, toetsenbordtoegang en focusstijlen toe te passen: en +beoordeelt UI vanuit de [zeven persona's](?path=/docs/curve-voor-developers--robuust-bouwen) +(blind/screenreader, slechtziend, kleurenblind, doof, beperkte motoriek, cognitief, situationeel). + +### Download + +

+ + Download de accessibility skill (accessibility.zip) + +

+ +Of download losse bestanden: + +| Bestand | Doel | +| ------------------------------------------------------ | -------------------------------------------- | +| [SKILL.md](./downloads/accessibility/SKILL.md) | Workflow, persona-review, output-sjabloon | +| [personas.md](./downloads/accessibility/personas.md) | Persona-definities en review-vragen | +| [reference.md](./downloads/accessibility/reference.md) | Semantische HTML, toetsenbord, labels, focus | + +### Installeren + +Pak `accessibility.zip` uit in de skills-map van je agent. De map moet `accessibility/` heten en +`SKILL.md` plus de andere bestanden bevatten. De YAML-frontmatter in `SKILL.md` is verplicht: agents +lezen `name` en `description` om te bepalen wanneer ze de skill laden. + +| Tool | Opslaan als | +| --------------------- | ------------------------------- | +| Cursor | `.cursor/skills/accessibility/` | +| Claude Code | `.claude/skills/accessibility/` | +| Codex / andere agents | `.agents/skills/accessibility/` | + +Zodra de skill geïnstalleerd is, geldt hij telkens wanneer de agent UI schrijft of beoordeelt. Voorbeelden: + +- "Beoordeel dit component op toegankelijkheid vanuit elke persona" +- "Wat zou een screenreadergebruiker missen in deze dialoog?" +- "Welk element krijgt focus als dit opengaat?" + +## Hoe je bruikbaar werk uit een agent krijgt + +**Vraag naar het mechanisme, niet naar het oordeel.** "Is dit toegankelijk?" nodigt uit tot een +zelfverzekerd ja. "Welk element krijgt focus als dit opengaat, en wat leest een screenreader voor?" +levert iets op dat je kunt controleren. + +**Laat ARIA verantwoorden.** Agents grijpen uit gewoonte naar ARIA-attributen. Vraag welk native element +het attribuut overbodig zou maken, en het meeste verdwijnt: zie +[Teveel ARIA](?path=/docs/curve-voor-developers-wat-vaak-mis-gaat--teveel-aria). + +**Geef het component mee, niet de klassenaam.** Een agent die weet dat Curve bestaat, stelt Button, +Dialog en Field samen. Een agent die vanaf een screenshot werkt, bouwt ze na uit `div`s en verliest elke +garantie die die primitieven bieden. + +**Laat hem de toetsenbordtest schrijven.** Agents zijn goed in het omzetten van een interactie naar een +Playwright- of Vitest-assertie. Focusvolgorde, Escape die een dialoog sluit, focus die terugkeert naar +de knop: precies de controles die zonder test langzaam wegroesten. + +## Wat een agent niet voor je kan doen + +Hij kan niet beoordelen of een kopstructuur klopt voor iemand die hem voor het eerst hoort, of iets een +link had moeten zijn in plaats van een knop, of jouw foutmelding iets uitlegt, of de flow werkt met +VoiceOver. Hij heeft jouw product nog nooit met een screenreader gebruikt. + +Behandel de output van een agent zoals je een linter behandelt: snel, onvermoeibaar, beperkt, en vaak +genoeg zelfverzekerd fout om +[de handmatige controle](?path=/docs/curve-voor-developers-je-werk-testen--handmatig-testen) +niet te vervangen. diff --git a/packages/storybook-config/docs/curve/03-voor-developers/05-wat-vaak-mis-gaat/01-naamloze-knoppen.mdx b/packages/storybook-config/docs/curve/03-voor-developers/05-wat-vaak-mis-gaat/01-naamloze-knoppen.mdx new file mode 100644 index 00000000..2e29dcec --- /dev/null +++ b/packages/storybook-config/docs/curve/03-voor-developers/05-wat-vaak-mis-gaat/01-naamloze-knoppen.mdx @@ -0,0 +1,51 @@ +import { Meta } from '@storybook/addon-docs/blocks'; + + + +# Naamloze knoppen + +Een [screenreadergebruiker](?path=/docs/curve-voor-developers--robuust-bouwen) +navigeert onder meer via een lijst met knoppen. Zonder toegankelijke naam blijft daar alleen de rol +over: "knop". + +## Het probleem + +Een icoonknop is visueel volstrekt duidelijk: een prullenbak, een kruis, een potlood. Voor wie de +pagina beluistert, is er geen prullenbak. Er is een bedienbaar element zonder naam. + +Hetzelfde gebeurt bij een invoerveld zonder `