Standardy · ARIA

Rola Widget złożony

menu

Oznacza kontener jako menu aplikacji — wyskakujące menu w stylu Plik/Edycja lub menu kontekstowe. Nie ma odpowiednika w HTML. Lista nawigacyjna serwisu NIE jest menu; zamiast niej użyj <nav> z listą <ul> zawierającą łącza.

Kiedy stosować

Dla menu w stylu aplikacji — wyskakującego po kliknięciu przycisku „Plik” lub menu kontekstowego po kliknięciu prawym przyciskiem, z nawigacją strzałkami i zamknięciem klawiszem Escape. Elementy potomne muszą mieć rolę role="menuitem", role="menuitemcheckbox", role="menuitemradio" lub role="separator".

Rola menu niesie semantykę aplikacji. Największy błąd w sieci to używanie role="menu" dla nawigacji serwisu — pułapkuje to użytkowników klawiatury w nawigacji strzałkami, błędnie ogłasza łącza jako pozycje menu i niszczy model mentalny użytkownika.

Zasada praktyczna: jeśli wyzwalacz jest hiperłączem, a pozycje są hiperłączami, to jest to nawigacja, a nie menu. Użyj <nav> i <ul>.

Menu MUSI mieć dostępną nazwę — użyj aria-label lub aria-labelledby wskazującego na wyzwalacz.

Klawiatura i zarządzanie fokusem

Zgodnie z wzorcem menu APG:

  • Przycisk wyzwalający ma aria-haspopup="menu" i aria-expanded. Aktywowanie wyzwalacza otwiera menu i przenosi fokus na pierwszą pozycję menuitem.
  • Wewnątrz menu: strzałki Góra/Dół przenoszą fokus między pozycjami; Home/End skaczą do pierwszej/ostatniej.
  • Strzałka w prawo otwiera podmenu (jeśli fokusowana pozycja je posiada); strzałka w lewo wraca do menu nadrzędnego.
  • Enter lub Spacja aktywuje fokusowaną pozycję i zamyka menu.
  • Escape zamyka menu i przywraca fokus na wyzwalaczu.
  • Typeahead: wpisanie litery przenosi fokus na następną pozycję zaczynającą się od tej litery.

Jeden punkt tabulacji: tylko jedna pozycja menuitem ma jednocześnie tabindex="0"; pozostałe mają -1.

Częste błędy

  • role="menu" na elemencie <nav>. Semantyka aplikacji nadpisuje semantykę nawigacji — czytniki ekranu przestają ogłaszać element jako punkt orientacyjny nawigacji.
  • Menu bez skojarzonego aria-haspopup="menu" na wyzwalaczu.
  • Escape zamyka menu, ale nie przywraca fokusu na wyzwalaczu, pozostawiając użytkownika bez orientacji.
  • Fokus NIE jest przenoszony na pierwszą pozycję menuitem po otwarciu menu — użytkownicy muszą przez nic tabulować.
  • Podmenu otwierane tylko po najechaniu kursorem, nie przez klawiaturę.

Przykład

<button id="actions" aria-haspopup="menu" aria-expanded="false" aria-controls="actionsMenu">
  Akcje
</button>
<ul id="actionsMenu" role="menu" aria-labelledby="actions" hidden>
  <li role="menuitem" tabindex="0">Edytuj</li>
  <li role="menuitem" tabindex="-1">Duplikuj</li>
  <li role="separator"></li>
  <li role="menuitem" tabindex="-1">Usuń</li>
</ul>