Gestalte barrierefreie Toggle-Buttons in React

Ob Filter-Optionen, System-Einstellungen oder ein Dark-Mode-Schalter – wahrscheinlich seid ihr im Internet schon mal auf einen Toggle-Button gestoßen. Diese erscheinen zunächst recht simpel: Sie erlauben den Nutzer:innen zwischen zwei Zuständen zu wechseln, meistens „ein“ und „aus“.

Leider gibt es kein natives HTML-Element für Toggle-Buttons. Aus diesem Grund geistern zahlreiche, selbstgebaute Implementierungen im Internet herum. Einige davon, ihr ahnt es schon, völlig unzugängliche Ungetüme.

Ein Mann steht hinter einem DJ Pult mit vielen Knöpfen und Drehschaltern. Foto: © Gaby Tenda / pexels.com

Ich habe eine Demo-Applikation in React mit barrierefreien Toggle-Buttons erstellt, die ich euch zeigen möchte. Ich bin mir nicht sicher, ob meine Lösung optimal ist. Daher würde ich mich über euer Feedback freuen.

Demo: Bier-Liste mit Toggle-Buttons

Meine Demo zeigt eine Liste verschiedener Biere. Nutzer:innen können über Toggle-Buttons zwischen schwachen und starken Bieren wechseln. Probiert es aus:

Wenn ihr den Code betrachtet, werdet ihr eine Gruppe von Buttons vorfinden, denen ich die switch Rolle zugewiesen habe. Bevor wir uns auf die technischen Details stürzen, möchte ich noch erklären, was ich mit dem Bedienelement erreichen möchte.

Ziele und Anforderungen

  1. Das Bedienelement soll seine Funktionalität klar vermitteln, sowohl visuell als auch für assistive Technologien.
  2. Es soll seinen aktuellen Zustand vermitteln, sowohl visuell als auch für assistive Technologien.
  3. Nutzer:innen sollen das Bedienelement allein mit der Tastatur bedienen können.
  4. Nur eine Option („schwach“ oder „stark“) kann gleichzeitig aktiv sein. Wenn eine Option aktiviert wird, wird die andere deaktiviert.
  5. Der Wechsel zwischen den beiden Optionen soll ein bewusster Akt der Nutzer:innen sein und nicht aus Versehen passieren.

Semantische Auszeichnung und Tastaturbedienung

Man könnte auch Radio-Buttons verwenden und ihr Styling mit CSS anpassen. Ich habe mich bewusst dagegen entschieden, weil diese bei Fokussierung automatisch aktiviert werden (was ich nicht will!) und zu den Standard-Formularelementen zählen. Web-Formulare sollen aber keinen Kontext-Wechsel auslösen, solange Nutzer:innen das Formular nicht bewusst abschicken.

Also habe ich mich dafür entschieden, ein button Element für jede auswählbare Option („schwach“ und „stark“) zu verwenden und ihnen die switch Rolle zuzuweisen. Die Spezifikation dieser Rolle lautet:

A type of checkbox that represents on/off values, as opposed to checked/unchecked values.

Meine React-Komponente beinhaltet einen Toggle-Button für jede Option. Auf diese Weisekann ich sie individuell beschriften und ihren Zustand (ein oder aus) eindeutig vermitteln. Weiters gruppiere ich die beiden Buttons in einem section Element mit group Rolle. Seht euch meinen JSX-Code an:

<section className={styles.container} role="group" aria-label={switchLabel}> <p>{switchLabel}:</p> <div className={styles.switchWrapper}> <button type="button" role="switch" aria-checked={selectedState === stateValues[0]} onClick={toggleSwitch} > {stateLabels[0]} </button> <button type="button" role="switch" aria-checked={selectedState === stateValues[1]} onClick={toggleSwitch} > {stateLabels[1]} </button> </div> </section>

Nutzer:innen können die Buttons mit der Tab-Taste fokussieren und sie mit der Enter- oder Leertaste ein- bzw. ausschalten.

Individuelles Styling mit CSS

Das Styling der Toggle-Buttons sorgt für die visuelle Vermittlung ihrer Funktionalität und ihres aktuellen Zustands. Wenn eine Option ausgewählt ist, invertiere ich ihre Farben und füge eine vertikale Linie mithilfe des ::after Pseudo-elements hinzu. Hier ein Auszug aus der SCSS-Datei meiner Komponente:

/* Invert background and text colors */ button[aria-checked="true"] { background: var(--light-black); color: white; } /* Add vertical line to highlight selected option */ button[aria-checked="true"]:after { content: ""; position: absolute; bottom: 0.2em; top: 0.2em; } button[aria-checked="true"]:first-of-type:after { right: 0.2em; border-right: 0.3em solid var(--primary-color); } button[aria-checked="true"]:last-of-type:after { left: 0.2em; border-left: 0.3em solid var(--primary-color); }

Feedback

Das war's. Mein Vorschlag für barrierefreie Toggle-Buttons. Was sagt ihr dazu? Genial oder einfach furchtbar? Sagt mir eure Meinung auf Twitter, Mastodon oder GitHub!

Nützliche Links

Erstellt am