Accessibilità · ARIA & tastiera
ARIA & widget da tastiera
Linee guida applicate ai componenti interattivi del prodotto. Riferimenti canonici: MDN — Accessible web apps & widgets e MDN — Keyboard-navigable JavaScript widgets .
1. Semantica prima, ARIA poi
La regola d'oro ARIA: non usare ARIA se esiste un elemento HTML nativo con la stessa semantica. Un <button> nativo è sempre preferibile a un <div role="button">perché eredita gratis: focus, attivazione con Invio/Spazio, ruolo, stato disabilitato.
Usiamo ARIA solo per arricchire ciò che HTML non esprime: stati dinamici (aria-expanded,aria-pressed, aria-selected), relazioni (aria-controls,aria-labelledby, aria-describedby) e regioni live (aria-live).
2. tabindex — quando e come
tabindex="0": rende focalizzabile un elemento non focalizzabile di default e lo inserisce nell'ordine naturale del DOM.tabindex="-1": focalizzabile solo via JavaScript (utile per spostare il focus, ad esempio su un dialog appena aperto o sul<main>dopo lo skip-link).- Mai usare
tabindexpositivo: rompe l'ordine di tab e crea barriere di navigazione.
3. Pattern di tasti per i widget composti
Per widget come tabs, menu, listbox, tree, combobox seguiamo i pattern di tastiera ARIA Authoring Practices:
- Tabs: ←/→ spostano la selezione, Home/End ai bordi, Tab esce dal widget.
- Menu / Listbox: ↑/↓ tra le voci, Esc chiude.
- Dialog modale: focus intrappolato finché aperto, Esc chiude, focus restituito al trigger.
- Toggle / Switch: Spazio commuta lo stato (
aria-pressedoaria-checked).
Questi pattern sono implementati nei nostri componenti Dialog, Switch, Tabs,Popover (basati su Radix UI, conformi a WAI-ARIA APG).
4. Focus management
- Indicatore di focus sempre visibile, contrasto ≥ 3:1 con lo sfondo (WCAG 2.4.13).
- Focus mai nascosto sotto barre sticky o tooltip (WCAG 2.4.11).
- Quando un'azione cambia contesto (apertura dialog, navigazione), spostiamo programmaticamente il focus al nuovo punto utile e lo restituiamo all'origine alla chiusura.
5. Stati e relazioni ARIA che usiamo
aria-current="page"sul link di nav attivo.aria-pressedsui toggle (Audio on/off, Riduci animazioni).aria-expanded+aria-controlsper disclosure.aria-live="polite"per messaggi non urgenti,aria-live="assertive"per errori bloccanti.aria-describedbyper collegare campi di form ai messaggi di errore.role="status"per stato runtime del sandbox di codice (Play/Stop, errori).
6. Cosa evitiamo
- Cliccabili senza ruolo (
<div onClick>) — sostituiti da<button>o link. - ARIA ridondante: ad esempio
role="button"su un<button>nativo. - Etichette solo visive (icone senza
aria-label) o solo testuali nascoste sotto immagini. - Tasti di scelta rapida che entrano in conflitto con quelli degli screen reader (per questo gli shortcut globali sono opzionali e documentati).