Przełącznik w filtrze powinien zmieniać widoczne wyniki, a ustawienie użytkownika powinno zachować spójny stan po każdej interakcji. Tailwind CSS ułatwia stylowanie stanów, lecz działanie kontrolki i jej dostępność zależą od HTML oraz logiki aplikacji.
Krótka odpowiedź
Użyj natywnego `
Wariant `aria-pressed:*` jest wbudowany od Tailwind CSS 3.2; `focus-visible:*` jest dostępny w Tailwind CSS 3, a w starszych wersjach zależy od konfiguracji wariantów.
Usługi KC Mobile
Potrzebujesz pomocy w tym temacie?
Czytasz poradnik „Tailwind CSS toggle: jak wdrożyć dostępny przełącznik”. Napisz, co chcesz zrobić i na jakim etapie jesteś. Ustalimy, czy możemy pomóc i jaki zakres prac będzie potrzebny.
Czym różni się toggle od zwykłego przycisku?
Toggle przełącza trwały stan między włączonym i wyłączonym, natomiast zwykły przycisk uruchamia jednorazową akcję, taką jak wysłanie formularza lub otwarcie okna. Przycisk "Dostępne od ręki" może aktywować filtr, a "Zapisz" wykonuje akcję i nie powinien pozostawać wciśnięty.
W filtrach kilka toggle może być aktywnych równocześnie, na przykład "Dostępne od ręki" oraz "Promocja". Gdy użytkownik ma wybrać jedną z opcji, takich jak widok listy albo siatki, rozważ pojedynczą grupę wyboru z właściwą semantyką zamiast niezależnych przycisków toggle.
Dla przycisku przełączającego zachowaj stałą nazwę, a stan podawaj przez `aria-pressed`. Przykładowo nazwa "Wycisz" może pozostać niezmieniona, gdy wartość `aria-pressed` przechodzi z `false` na `true`. Jeśli zmieniasz nazwę z "Wycisz" na "Włącz dźwięk", zwykle komunikujesz stan już tekstem i trzeba rozważyć zwykłą akcję zamiast przycisku toggle.
Czytasz poradnik „Tailwind CSS toggle: jak wdrożyć dostępny przełącznik”. Napisz, co chcesz zrobić i na jakim etapie jesteś. Ustalimy, czy możemy pomóc i jaki zakres prac będzie potrzebny. Omów temat tego poradnika
Jak przygotować strukturę przycisku w Tailwind CSS?
Zacznij od semantycznego `
<button
type="button"
aria-pressed="false"
class="inline-flex min-h-11 items-center rounded-md border border-slate-300 bg-white px-4 py-2 text-sm font-medium text-slate-800 hover:bg-slate-50 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-violet-700 aria-pressed:bg-violet-700 aria-pressed:text-white"
>
Dostępne od ręki
</button>`min-h-11` i `px-4 py-2` określają obszar kontrolki, `border-*`, `bg-*` i `text-*` odpowiadają za kolory, a `focus-visible:outline-*` wyświetla obrys przy nawigacji klawiaturą. `aria-pressed:bg-violet-700` i `aria-pressed:text-white` zmienią styl, gdy przycisk ma atrybut `aria-pressed="true"`.
Sprawdź wersję Tailwind w `package.json`, pliku blokady zależności lub komendą `npx tailwindcss --version`. Wariant `aria-pressed:*` dodano do wbudowanych wariantów w Tailwind CSS 3.2. W Tailwind CSS 3 wariant `focus-visible:*` jest dostępny w standardowym zestawie; w Tailwind CSS 2 warianty stanów zależą od konfiguracji w `tailwind.config.js`, a wbudowany wariant `aria-pressed:*` nie jest domyślnie dostępny. W starszym projekcie dodaj odpowiedni wariant w konfiguracji, użyj własnego CSS z selektorem `[aria-pressed="true"]` albo zaktualizuj wersję. Dokumentacja stanów Tailwind CSS 3 oraz Tailwind CSS 4 pokazuje dostępne warianty.
Tekst tworzy nazwę przycisku. Jeżeli pokazujesz samą ikonę, zapewnij kontrolce nazwę opisującą działanie i sprawdź ją w drzewie dostępności. Kolor aktywnego stanu uzupełnij drugim sygnałem, takim jak obrys lub widoczna zmiana oznaczenia.
Jak przełączać stan i zmieniać wygląd?
Obsługa kliknięcia powinna w jednym miejscu zaktualizować stan kontrolki i wykonać jej właściwe działanie. W tym przykładzie JavaScript filtruje elementy oznaczone `data-available`, zmieniając ich właściwość `hidden`.
<button
id="availability-toggle"
type="button"
aria-pressed="false"
class="rounded-md border px-4 py-2 aria-pressed:bg-violet-700 aria-pressed:text-white focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-violet-700"
>
Dostępne od ręki
</button>
<p id="results-count" aria-live="polite" aria-atomic="true"></p>
<ul>
<li data-available="true">Produkt dostępny</li>
<li data-available="false">Produkt na zamówienie</li>
</ul>
<script>
const toggle = document.querySelector("#availability-toggle");
const products = [...document.querySelectorAll("[data-available]")];
const count = document.querySelector("#results-count");
function updateResults(isPressed) {
let visibleCount = 0;
products.forEach((product) => {
const visible = !isPressed || product.dataset.available === "true";
product.hidden = !visible;
if (visible) visibleCount += 1;
});
count.textContent = `Liczba produktów: ${visibleCount}.`;
}
toggle.addEventListener("click", () => {
const nextState = toggle.getAttribute("aria-pressed") !== "true";
toggle.setAttribute("aria-pressed", String(nextState));
updateResults(nextState);
});
</script>Region `aria-live="polite"` ogłasza zmianę liczby wyników, ponieważ sam `aria-pressed` informuje tylko o stanie kontrolki. Komunikat nie powinien odczytywać każdej pozycji listy; przekazuje zmianę, która pomaga zrozumieć efekt filtra. Przy dużej liście możesz uruchomić zapytanie do API zamiast ukrywać istniejące elementy, ale obsłuż także stan ładowania i błąd odpowiedzi.
Jeśli źródłem listy jest serwer, zaktualizuj wyniki dopiero zgodnie z ustalonym zachowaniem żądania. Nie pozostawiaj aktywnego wizualnie przełącznika, gdy żądanie zakończyło się błędem i filtr nie zadziałał. W aplikacji frameworkowej stan powinien należeć do tego frameworka, a DOM ma z niego wynikać.

Który wariant wdrożenia wybrać?
Wybierz technologię, która już zarządza stanem danego widoku. Pojedynczy toggle nie uzasadnia dodania frameworka do strony, ale powielona logika w kilku miejscach może uzasadniać wspólny komponent.
| Wariant | Zależności | Kiedy pasuje | Co utrzymywać |
|---|---|---|---|
| HTML i JavaScript | Bez frameworka | Jeden filtr albo ustawienie w małym widoku | Obsługę zdarzenia, stan i aktualizację wyników |
| Alpine.js | Alpine.js obecny na stronie | Lekka interakcja w komponencie HTML | Stan w `x-data` i powiązanie go z atrybutem oraz widokiem |
| React | Interfejs lub wyspa React | Stan listy i filtrów już należy do komponentów React | Stan React, komponent oraz przekazanie wyników |
Przykład Alpine.js używa `x-data` do przechowania stanu, a `@click` do jego zmiany. Atrybut `:aria-pressed` i licznik wyników odczytują tę samą wartość:
<div x-data="{ active: false, count: 12 }">
<button type="button" :aria-pressed="active.toString()" @click="active = !active; count = active ? 4 : 12"
class="rounded-md border px-4 py-2 aria-pressed:bg-violet-700 aria-pressed:text-white focus-visible:outline-2 focus-visible:outline-offset-2">
Dostępne od ręki
</button>
<p aria-live="polite" x-text="`Liczba produktów: ${count}.`"></p>
</div>Przykład React przechowuje stan w `useState` i renderuje z niego zarówno atrybut, jak i tekst licznika:
import { useState } from "react";
function AvailabilityToggle() {
const [active, setActive] = useState(false);
const count = active ? 4 : 12;
return (
<div>
<button
type="button"
aria-pressed={active}
onClick={() => setActive((value) => !value)}
className="rounded-md border px-4 py-2 aria-pressed:bg-violet-700 aria-pressed:text-white focus-visible:outline-2 focus-visible:outline-offset-2"
>
Dostępne od ręki
</button>
<p aria-live="polite" aria-atomic="true">Liczba produktów: {count}.</p>
</div>
);
}W przykładach licznik jest uproszczony; w produkcyjnym filtrze obliczaj go z faktycznie wyświetlanej listy. Alpine wiąże zdarzenia przez `x-on` lub skrót `@` w zasięgu `x-data`; React renderuje aktualizację z własnego stanu komponentu. Zobacz dokumentacje Alpine.js i stanu komponentu React, aby dopasować kod do aplikacji.
Jak obsłużyć fokus, klawiaturę i czytniki ekranu?
Natywny przycisk zapewnia obsługę klawiatury bez własnych handlerów `keydown`. Tab przenosi fokus, a Enter i Spacja aktywują kontrolkę; dodatkowe ręczne wywoływanie kliknięcia dla tych klawiszy może spowodować podwójne działanie.
Pozostaw widoczny fokus podczas nawigacji klawiaturą. `focus-visible:outline-2` tworzy obrys, ale sprawdź jego kontrast na tle strony, aktywnego przycisku i sąsiednich elementów. Nie usuwaj wskaźnika klasą `outline-none`, jeśli nie zastępujesz go równie widocznym oznaczeniem.
Czytnik ekranu odczytuje nazwę przycisku oraz stan `aria-pressed`. Przy toggle utrzymaj tę samą nazwę dla obu stanów, aby użytkownik rozumiał, że przełączył funkcję. Gdy aktywacja prowadzi do nowego kontekstu, na przykład otwiera dialog, zastosuj zasady fokusu właściwe dla tego wzorca zamiast traktować go jak filtr.
Dla filtrów liczba wyników to osobna informacja. Zaktualizuj region `aria-live="polite"` po przeliczeniu listy i podaj krótką zmianę, taką jak "Liczba produktów: 4". Gdy wynik jest aktualizowany przy każdym kliknięciu kilku filtrów, aktualizuj jeden region z końcową liczbą, a nie wiele komunikatów opisujących pośrednie etapy.
Jak uniknąć typowych błędów w toggle button?
Błędy powstają, gdy styl komponentu i funkcja aplikacji mają niezależne stany. Tabela pomaga znaleźć, czy problem dotyczy HTML, logiki, czy komunikowania wyniku.
| Błąd | Skutek | Poprawka |
|---|---|---|
| Zmienia się kolor, ale nie `aria-pressed` | Czytnik ekranu otrzymuje nieaktualny stan | Aktualizuj atrybut z tego samego źródła stanu co wygląd |
| Zmienia się `aria-pressed`, ale lista pozostaje bez zmian | Kontrolka sygnalizuje efekt, którego użytkownik nie widzi | Powiąż stan z filtrem i ogłoś nową liczbę wyników |
| Elementem jest `div` albo link bez nawigacji | Brakuje oczekiwanej semantyki i obsługi klawiatury | Zastosuj natywny ` |
| Fokus znika po użyciu `outline-none` | Użytkownik klawiatury traci informację o położeniu | Zapewnij i sprawdź widoczny obrys fokusu |
| Etykieta zmienia się równocześnie z `aria-pressed` | Nazwa może dublować albo zaciemniać stan | Zachowaj nazwę toggle lub wybierz wzorzec zwykłej akcji |
| Filtr zmienia listę bez komunikatu o liczbie wyników | Użytkownik czytnika może nie zauważyć efektu | Aktualizuj jeden spokojny region live po zmianie listy |
Perspektywa KC Mobile: przy filtrach sprawdzamy efekt w danych i licznikach obok samego kliknięcia. Typowy problem to przycisk, który zmienia kolor, podczas gdy lista nie reaguje, bo kontrolka nie jest połączona z logiką widoku. Jeśli filtr ma być zapamiętany, sprawdzamy też zachowanie po ponownym załadowaniu strony.
Jak sprawdzić przełącznik przed publikacją?
Przetestuj kontrolkę na telefonie i komputerze, a następnie sprawdź efekty interakcji poza samym przyciskiem. Wąski ekran może zmienić układ filtrów, a prawidłowy `aria-pressed` nie dowodzi jeszcze, że lista zmieniła się zgodnie z oczekiwaniem.
| Test | Działanie | Oczekiwany wynik |
|---|---|---|
| Stan początkowy | Otwórz stronę i sprawdź filtr | Wygląd, `aria-pressed` i widok odpowiadają sobie |
| Aktywacja i ponowna aktywacja | Kliknij, a potem wyłącz filtr | Stan przechodzi w obie strony, wyniki aktualizują się |
| Klawiatura | Przejdź Tabem i aktywuj Enterem oraz Spacją | Fokus jest widoczny, każde użycie powoduje pojedynczą zmianę |
| Czytnik ekranu | Odczytaj przycisk i zmień filtr | Nazwa jest zrozumiała, stan i liczba wyników są ogłoszone |
| Zmiana szerokości | Sprawdź szeroki i wąski widok | Etykieta, fokus i kontrolka pozostają widoczne |
| Współdziałanie filtrów | Włącz dwa filtry, zmień sortowanie i wyczyść filtry | Lista i licznik odpowiadają aktywnym ustawieniom |
W narzędziach deweloperskich przeglądarki obserwuj `aria-pressed` w panelu Elements. Dla przykładowego elementu możesz odczytać wartość w konsoli: `document.querySelector("#availability-toggle").getAttribute("aria-pressed")`. Testuj także wynik listy i treść regionu na żywo, ponieważ atrybut przycisku sam nie potwierdza działania filtra.
Sprawdź, czy kompilator Tailwind nie usunął klas użytych w komponentach generowanych dynamicznie. Jeśli składasz nazwę klasy z fragmentów tekstu, na przykład `aria-pressed:bg-` oraz zmiennego koloru, skaner może nie wykryć pełnej klasy; użyj pełnych nazw klas albo skonfiguruj źródła skanowania zgodnie z wersją Tailwind. Gdy projekt ma wspólny system komponentów, wdrożenie Tailwind CSS może objąć dopasowanie wariantów, logiki oraz testów do istniejącego stosu.

Więcej poradników w tym temacie
Wspomniane narzędzia
Najczęściej zadawane pytania
Jak zrobić toggle button w Tailwind CSS?
Czy Tailwind CSS ma gotowy komponent toggle?
Jak zmienić kolor aktywnego przycisku toggle w Tailwind CSS?
Jak dodać aria-pressed do przycisku Tailwind?
Czy do przełącznika Tailwind CSS potrzebuję JavaScriptu?
Potrzebujesz pomocy w tym temacie?
Czytasz poradnik „Tailwind CSS toggle: jak wdrożyć dostępny przełącznik”. Napisz, co chcesz zrobić i na jakim etapie jesteś. Ustalimy, czy możemy pomóc i jaki zakres prac będzie potrzebny.
