Zurück zur Startseite

Barrierefreier DatePicker React WCAG 2.2

Der Artikel beschreibt das Erstellen eines WCAG 2.2 AA DatePicker mit React mit KI-Generierungs-Korrekturen. Behandelt Abweichungen von APG, Fokus-Management, aria-live assertive. Für Senior-Entwickler.

WCAG DatePicker mit React: von KI zum Ideal
Advertisement 728x90

Barrierefreier React-DatePicker nach WCAG 2.2 AA-Standards

Unser Entwicklerteam ist mit Claude-generiertem DatePicker-Code gestartet, basierend auf dem WAI-ARIA APG „Date Picker Dialog“-Pattern. Der anfängliche Prompt spezifizierte WCAG 2.1/2.2 Level-AA-Anforderungen: Eingabefeld mit aria-describedby, Auslöse-Button, modales Dialog mit role="dialog" und kalenderbasierter Gittertabelle. Die rohe Version zeigte jedoch kritische Probleme bei Fokus, Navigation und Barrierefreiheit.

Die KI implementierte grundlegende Tastaturnavigation (Pfeiltasten, Pos1/Ende, Bild hoch/runter, Eingabe/Leertaste, Escape), wandernden tabindex auf gridcell-Elementen und aria-live="polite" für Monatswechsel. Tests mit VoiceOver und NVDA deckten jedoch Probleme auf: Der Fokus landete beim Öffnen nicht auf dem ausgewählten Datum, aria-live-Ankündigungen stauten sich, und das Dialog flackerte bei wiederholten Klicks.

Abweichungen vom APG für Praxis-Barrierefreiheit

Die APG-Spezifikation fordert <td role="gridcell"> ohne verschachtelte Buttons, mit manuellen onClick/onKeyDown und tabindex. Praxis-Tests zeigten klare Vorteile bei <button> innerhalb von <td>:

Google AdInline article slot
  • Native Fokusbehandlung und Unterstützung für Eingabe/Leertaste ohne Extra-Code.
  • Automatische Semantik für Screenreader.
  • Eingebauter deaktivierter Zustand ohne aria-disabled oder preventDefault.
  • Zuverlässige Klick-Events per Maus oder Tastatur.

Das war eine bewusste Entscheidung: APG ist eine Orientierung, aber Gerätetests haben Vorrang. Wir stellten ≥4,5:1 Kontrast sicher, nutzten CSS-Module und native Date/Intl-APIs für Formatierung – keine externen Abhängigkeiten außer React/TypeScript.

Behebung funktionaler und UX-Probleme

Der Rohcode ließ sich nicht kompilieren: fehlende index.html und TypeScript-Fehler. Nach Korrekturen tauchten weitere Probleme auf:

Funktionale Bugs:

Google AdInline article slot
  • Daten außerhalb minDate/maxDate sprangen in einen anderen Monat statt deaktivierte Zellen zu zeigen.
  • Keine Möglichkeit, das Eingabefeld zu löschen.

Visuelle Probleme:

  • Fehlende Fokus-Stile auf Zellen.
  • Ungleiche td-Größen.

Barrierefreiheit:

  • Kein Fokus auf ausgewähltem Datum beim Öffnen – Screenreader blieben stumm.
  • aria-live="polite" am Monats-Header führte zu Ankündigungsstaus bei schneller Navigation.
  • Blur + Klick auf Auslöser verursachte Dialog-Flackern.

Lösungen:

Google AdInline article slot
  • Beim Öffnen landet Fokus auf Wert oder heute; Screenreader kündigt Kontext an (Wochentag, Datum, Monat, Jahr).
  • aria-live="assertive" in separater versteckter Region für sofortige Monatsankündigungen.
  • Nach Auswahl kehrt Fokus zum Auslöser mit aktualisiertem aria-label zurück.
  • Zeige Monat des Werts auch bei deaktivierten Tagen.
  • OK/Abbrechen entfernt: Eingabe bestätigt, Esc schließt.

Komponentenstruktur und Tastaturnavigation

Props: value (Date | null), onChange, minDate?, maxDate?, disabledDates?, locale?.

Wichtige ARIA:

  • Eingabe: aria-describedby für Format, readonly.
  • Auslöser: dynamisches aria-label („Ausgewählt: TT.MM.JJJJ“ oder „Datum wählen“).
  • Dialog: role="dialog", aria-modal="true", Fokusfalle.
  • Gitter: table role="grid", td mit button role="gridcell", aria-selected auf Wert, aria-disabled auf nicht verfügbare Daten.
  • Monats-Header: aria-live="assertive" in polite-Region.

Navigation:

  • Pfeiltasten: benachbarte Tage.
  • Pos1/Ende: erster/letzter Tag des Monats.
  • Bild hoch/runter: ±1 Monat.
  • Umschalt+Bild hoch/runter: ±1 Jahr.
  • Eingabe/Leertaste: auswählen.
  • Escape: schließen.

Wichtigste Erkenntnisse

  • KI beschleunigt das Gerüst (ARIA, Navigation), aber Screenreader-Tests sind essenziell.
  • <button> in <td> ist in realen Browsern + Screenreadern zuverlässiger als reines gridcell.
  • aria-live="assertive" verhindert Staus bei Monatsnavigation.
  • Fokus-Management: Öffnen auf Wert/heute, Rückkehr zum Auslöser.
  • Minimaler Stack: React + TS, keine Bibliotheken.

Die Komponente ist produktionsreif als Einzeldatum-Picker, mit offenem Code für Erweiterungen (Jahre, Bereiche).

— Editorial Team

Advertisement 728x90

Weiterlesen