Implementace přístupného DatePickeru v React podle WCAG 2.2 AA
Tým vývojářů vycházel z kódu DatePickeru vygenerovaného Claude podle vzoru WAI-ARIA APG „Date Picker Dialog“. Původní prompt zahrnoval požadavky WCAG 2.1/2.2 úroveň AA: struktura s inputem, aria-describedby, tlačítkem triggerem, modálním dialogem role="dialog" a mřížkou kalendáře. Surová verze však odhalila kritické chyby v zaměřování, navigaci a přístupnosti.
AI vytvořil základní klávesovou navigaci (šipky, Home/End, PageUp/Down, Enter/Mezerník, Escape), roaming tabindex na gridcell, aria-live="polite" pro měsíc. Testování na VoiceOver a NVDA však ukázalo: zaměření se nedostalo na vybraný datum při otevření, aria-live hromadilo frontu zpráv, dialog blikalo při opakovaném kliknutí.
Úpravy oproti APG pro praktickou přístupnost
Specifikace APG předepisuje <td role="gridcell"> bez vnořených tlačítek, s manuálním onClick/onKeyDown a tabindex. Praxe odhalila výhody <button> uvnitř <td>:
- Nativní zpracování zaměření, Enter/Mezerník bez dalšího kódu.
- Automatická sémantika pro čtečky obrazovky.
- Podpora disabled bez aria-disabled a preventDefault.
- Stabilní click události od myši/klávesnice.
Toto je vědomé odchylení: specifikace je směrnicí, ale reálné testy na zařízeních mají přednost. Kontrast ≥4.5:1, CSS Modules, nativní Date a Intl pro formátování – bez externích závislostí kromě React/TypeScript.
Oprava funkčních a UX chyb
Surový kód se nekompiloval: chyběl index.html, TypeScript chyby. Po opravách se projevily:
Funkční chyby:
- Datum mimo minDate/maxDate přeskakovalo na jiný měsíc místo zobrazení disabled buněk.
- Nedaří se vyčistit input.
Vizuální problémy:
- Chybí focus styl na buňkách.
- Nerovnoměrné velikosti td.
Přístupnost:
- Žádné zaměření na datum při otevření – čtečka obrazovky mlčí.
- aria-live="polite" na hlavičce měsíce: fronta zpráv při rychlém přepínání.
- Blur+klik na trigger způsobovalo blikání dialogu.
Opravy:
- Zaměření při otevření na value nebo today, čtečka čte kontext (den v týdnu, datum, měsíc, rok).
- aria-live="assertive" v oddělené skryté oblasti pro okamžité oznámení měsíce.
- Po výběru – zaměření na trigger s aktualizovaným aria-label.
- Zobrazení měsíce value i s disabled dny.
- Odstraněny OK/Zrušit: Enter potvrzuje, Esc zavírá.
Struktura komponenty a klávesová navigace
Props: value (Date | null), onChange, minDate?, maxDate?, disabledDates?, locale?.
Klíčové ARIA:
- Input: aria-describedby pro formát, readonly.
- Trigger: dynamický aria-label ("Vybráno: DD.MM.RRRR" nebo "Vyberte datum").
- Dialog: role="dialog", aria-modal="true", focus trap.
- Mřížka: table role="grid", td s button role="gridcell", aria-selected na value, aria-disabled na nepřístupných.
- Hlavička měsíce: aria-live="assertive" v polite oblasti.
Navigace:
- Šipky: sousední dny.
- Home/End: první/poslední den měsíce.
- PageUp/Down: ±1 měsíc.
- Shift+PageUp/Down: ±1 rok.
- Enter/Mezerník: výběr.
- Escape: zavření.
Co je důležité
- AI urychluje kostru (ARIA, navigace), ale vyžaduje manuální testování čtečkami.
- <button> v <td> je spolehlivější než čistý gridcell pro reálné prohlížeče+čtečky.
- aria-live="assertive" pro navigaci měsíci zabraňuje frontě.
- Správa zaměření: otevření na value/today, návrat na trigger.
- Minimální stack: React + TS, bez knihoven.
Komponenta je připravená pro produkci jako single-date picker, s otevřeným kódem pro další úpravy (roky, rozsahy).
— Editorial Team
Zatím žádné komentáře.