Standardy · ARIA

Rola Widget

tab

Oznacza element jako jeden tab w interfejsie z kartami. Tab MUSI znajdować się wewnątrz tablist i POWINIEN wskazywać powiązany tabpanel przez aria-controls. Nie istnieje natywny element HTML dla kart — wzorzec ten oparty jest wyłącznie na ARIA.

Kiedy używać

Dla jednej karty w poziomym lub pionowym pasku kart. Tab MUSI być bezpośrednim dzieckiem elementu role="tablist" (lub należeć do niego przez aria-owns). Każdy tab MUSI wskazywać powiązany panel przez aria-controls="<tabpanel-id>". Zwrotny aria-labelledby umieszcza się na panelu i wskazuje z powrotem na tab.

Karty to wzorzec aplikacyjny. Jeśli „karty” są tak naprawdę nawigacją między oddzielnymi stronami, użyj <nav> z łączami <a> — zmiana URL sprawia, że wzorzec kart jest nieodpowiedni.

Sam tab to zazwyczaj <button>. Semantyka przycisku łączy się naturalnie z role="tab", a obsługa fokusu i aktywacji jest zapewniona bezpłatnie.

Kontrakt klawiatury i fokusu

Zgodnie z wzorcem APG dla kart:

  • Tab przenosi fokus do tablist, na aktywną kartę. Tab przenosi fokus NA ZEWNĄTRZ do kolejnego elementu (zazwyczaj do tabpanel, jeśli ma tabindex="0").
  • Strzałki Lewo/Prawo (lub Góra/Dół dla pionowych tablist) przesuwają fokus między kartami.
  • Home / End przeskakują do pierwszej / ostatniej karty.
  • Aktywacja może być automatyczna (fokus = wybór) lub ręczna (Space/Enter do wyboru). Wybierz tryb ręczny, gdy aktywacja karty wyzwala kosztowne operacje.

Stosuj roving tabindex: tylko wybrana karta ma tabindex="0".

Typowe błędy

  • Wszystkie karty z tabindex="0" — Tab przechodzi przez każdą kartę zamiast przez panel.
  • Brak aria-controls łączącego kartę z tabpanel.
  • aria-selected="true" na więcej niż jednej karcie.
  • Karty zrealizowane z <a href="#section"> — fragment URL ulega zmianie, przycisk „wstecz” nawiguje między kartami i wzorzec się rozpada.
  • Brak zarządzania fokusem po aktywacji: kliknięcie karty aktualizuje panel, ale kolejne naciśnięcie Tab wraca do nagłówka strony zamiast do panelu.

Przykład

<div role="tablist" aria-label="Account settings">
  <button role="tab" id="t-profile"  aria-selected="true"  aria-controls="p-profile"  tabindex="0">Profile</button>
  <button role="tab" id="t-billing"  aria-selected="false" aria-controls="p-billing"  tabindex="-1">Billing</button>
  <button role="tab" id="t-security" aria-selected="false" aria-controls="p-security" tabindex="-1">Security</button>
</div>
<section role="tabpanel" id="p-profile"  aria-labelledby="t-profile"  tabindex="0">…</section>
<section role="tabpanel" id="p-billing"  aria-labelledby="t-billing"  hidden>…</section>
<section role="tabpanel" id="p-security" aria-labelledby="t-security" hidden>…</section>