Normative · ARIA

Ruolo Widget

menuitem

Contrassegna un elemento come voce azionabile all'interno di un menu o menubar. Non esiste un equivalente HTML — i menu sono un costrutto esclusivo di ARIA. Si utilizzi questo ruolo solo quando si sta costruendo un menu applicativo vero e proprio; un semplice elenco di navigazione NON dovrebbe usare menu/menuitem.

Quando usarlo

Solo all’interno di un role="menu" o role="menubar", e unicamente quando il menu è un menu applicativo — il tipo che riproduce la barra File/Modifica/Visualizza di un’applicazione desktop, con singolo tab-stop, navigazione tramite tasti freccia e Esc per chiudere.

La navigazione principale di un sito NON è un menu. Si utilizzi <nav> con un <ul> di link <a>. Confondere i due costrutti è l’errore ARIA più diffuso sul web — intrappola gli utenti da tastiera nella navigazione con i tasti freccia quando Tab sarebbe più naturale, e comunica ai screen reader «menu applicativo» quando il contenuto è semplicemente un insieme di link.

Ruoli correlati: menuitemcheckbox (per voci di menu che attivano/disattivano un’opzione) e menuitemradio (per scelte esclusive all’interno di un menu).

Contratto tastiera + focus

Secondo il pattern APG menu:

  • Tab entra ed esce dal menu — il focus si sposta sul primo menuitem all’ingresso. Tab NON scorre tra le voci.
  • I tasti Su/Giù spostano il focus tra le voci (con avvolgimento circolare).
  • Destra/Sinistra aprono i sottomenu / tornano al genitore.
  • Invio o Spazio attivano la voce in focus.
  • Escape chiude il menu e riporta il focus sul trigger.
  • La digitazione di una lettera sposta il focus alla voce successiva che inizia con quella lettera (typeahead).

Si utilizzi un roving tabindex: solo il menuitem attualmente in focus ha tabindex="0"; tutti gli altri hanno tabindex="-1".

Errori comuni

  • Usare role="menuitem" per un semplice link nella navigazione del sito. Causa trappole da tastiera e annunci errati del screen reader.
  • Ogni menuitem con tabindex="0", così Tab scorre per ciascuno. Il pattern prevede un singolo tab-stop.
  • Sottomenu che si aprono al passaggio del mouse ma non con il tasto Destra.
  • Escape chiude il sottomenu ma perde il focus, lasciando l’utente spaesato fuori dal menu.
  • Voci prive di nome accessibile perché l’icona è l’unico contenuto — aggiungere aria-label.

Esempio

<button id="fileBtn" aria-haspopup="menu" aria-expanded="false" aria-controls="fileMenu">
  File
</button>
<ul id="fileMenu" role="menu" aria-labelledby="fileBtn" hidden>
  <li role="menuitem" tabindex="0">Nuovo</li>
  <li role="menuitem" tabindex="-1">Apri</li>
  <li role="menuitem" tabindex="-1" aria-haspopup="menu" aria-expanded="false">
    Apri recente
  </li>
  <li role="separator"></li>
  <li role="menuitem" tabindex="-1">Salva</li>
</ul>