Test accessibilità
Pagina di test per verificare il comportamento dell’accessibility tree e dei tool di verifica automatica sui web component Dev Kit Italia.
Contesto e scopo
Questa pagina fa parte di un’analisi esplorativa sulla verificabilità dell’accessibilità dei siti che usano Dev Kit Italia. I componenti <it-*> usano shadow DOM per incapsulare markup e stili, e slot per ricevere contenuto dal light DOM. Questo approccio funziona bene con screen reader e browser moderni, ma mette in difficoltà diversi tool di verifica automatica.
La pagina raccoglie casi di test pensati per forzare errori controllati e confrontare come diversi tool (axe-core, Siteimprove, ARC Toolkit, WAVE, pa11y, MAUVE++) li rilevano o non li rilevano.
Gli errori in questa pagina sono intenzionali — servono a misurare la copertura dei tool, non a suggerire pattern d’uso dei componenti.
Cosa questa pagina non è
Questa pagina non valuta l’accessibilità di Dev Kit Italia. I componenti sono stati sviluppati seguendo le migliori pratiche WAI-ARIA e verificati durante lo sviluppo con controlli estesi:
- resa, comportamenti e funzionalità su combinazioni di sistema operativo (Windows, macOS), device (desktop, mobile iOS e Android) e browser (Firefox, Chrome, Edge, Safari)
- lettori di schermo: VoiceOver, NVDA, JAWS
- resa senza JavaScript (FOUC)
- strumenti di verifica automatica (axe, Siteimprove, WAVE)
- ingrandimento schermo e responsive
- navigazione da tastiera
- rispetto delle migliori pratiche WAI-ARIA
L’obiettivo di questa pagina è diverso: verificare come gli strumenti di verifica automatica rilevano eventuali errori d’uso quando i componenti vengono applicati in un sito reale (slot non popolati, contrasti forzati, ARIA cross-scope, gerarchie heading miste). Questi errori dipendono da come il dev usa i componenti, non dai componenti stessi.
Come leggere la pagina
Ogni sezione include un 🔴 errore intenzionale su un web component Dev Kit e lo stesso errore su HTML classico come controllo. Se il tool segnala entrambi, e riconosce anche i casi 🟢 controllo, è possibile dedurre che stia verificando dentro il shadow DOM, salvo verificare in ogni caso i risultati.
Legenda:
- 🟢 Controllo OK — componente corretto, un tool accurato deve passarlo senza segnalazioni
- 🔴 Errore intenzionale — errore controllato, un tool accurato deve segnalarlo
- 🟡 Verifica comportamentale — da osservare manualmente (focus, form submit, screen reader)
Test con pa11y da CLI
La pagina è direttamente testabile ad esempio con pa11y:
bashEngine HTML_CodeSniffer (default)
npx pa11y https://italia.github.io/design-jekyll-devkit-theme/test-a11y/ --standard WCAG2AA --runner axe
A. Slot vuoti — elementi semantici fantasma
Quando uno slot obbligatorio non viene popolato, il componente Dev Kit genera comunque l’elemento semantico nel shadow DOM (heading, label, button), producendo un nodo accessibile con nome vuoto. Dev Kit segnala il problema in console ma il DOM non reagisce.
Card
Card completa (🟢 controllo ok)
Card senza slot title (🔴 errore intenzionale)
Card completamente vuota (🔴 errore intenzionale)
Card senza slot title con immagine (🔴 errore intenzionale)
Card con slot title vuoto (🔴 errore intenzionale)
Card full-height senza title (🔴 errore intenzionale)
Accordion
Accordion completo (🟢 controllo ok)
Accordion senza slot heading (🔴 errore intenzionale)
Accordion item vuoto (🔴 errore intenzionale)
Input
Input con label (🟢 controllo ok)
Input senza label (🔴 errore intenzionale)
Button
Button con testo (🟢 controllo ok)
Button senza testo (🔴 errore intenzionale)
Callout
Callout completo (🟢 controllo ok)
Testo del callout di esempio.
Callout senza slot title (🔴 errore intenzionale)
Testo del callout senza titolo.
Modal
Modal completa (🟢 controllo ok)
Contenuto della modale.
Modal senza slot header (🔴 errore intenzionale)
Contenuto senza titolo.
Dropdown
Dropdown completo (🟢 controllo ok)
Dropdown senza label (🔴 errore intenzionale)
Select
Select con label (🟢 controllo ok)
Select senza label (🔴 errore intenzionale)
Checkbox
Checkbox con label (🟢 controllo ok)
Checkbox senza label (🔴 errore intenzionale)
Radio button
Radio group completo (🟢 controllo ok)
Radio group senza label (🔴 errore intenzionale)
Breadcrumbs
Breadcrumbs completo (🟢 controllo ok)
Breadcrumbs vuoto (🔴 errore intenzionale)
Chip
Chip con label (🟢 controllo ok)
Chip senza label (🔴 errore intenzionale)
Hero
Hero con contenuto (🟢 controllo ok)
Hero vuoto (🔴 errore intenzionale)
B. Contrasto colori nel shadow DOM
Verifica se i tool calcolano il contrasto sui testi renderizzati nel shadow DOM dei componenti, confrontando lo stesso errore applicato in due modi diversi:
- Via style sugli slot (light DOM): il tool deve solo leggere lo style inline
- Via
::part()(shadow DOM): il tool deve attraversare il shadow DOM per calcolare il contrasto
La seconda forma è il vero banco di prova — un tool che non entra nel shadow DOM non può calcolare il contrasto corretto.
Card Dev Kit con contrasto 🔴 errato (via style sugli slot)
HTML classico con stesso contrasto 🔴 errato (controllo)
Titolo con contrasto insufficiente
Testo con contrasto insufficiente — grigio chiaro su bianco (#aaa su #fff = ratio 2.32:1).
Card Dev Kit con contrasto corretto (🟢 controllo ok)
Callout con testo su sfondo colorato
Testo su sfondo colorato — il contrasto è verificato dai tool?
Chip varianti colore
B. Contrasto colori test con parts
Verifica se i tool calcolano il contrasto sui testi renderizzati nel shadow DOM.
Il test usa il selettore ::part() per forzare un colore a basso contrasto
sugli elementi dentro il shadow DOM dei web component.
Card Dev Kit con contrasto 🔴 errato (via ::part nel shadow DOM)
HTML classico con stesso contrasto 🔴 errato (controllo)
Titolo con contrasto insufficiente
Testo con contrasto insufficiente — grigio chiaro su bianco (#aaa su #fff = ratio 2.32:1).
Card Dev Kit con contrasto corretto (🟢 controllo ok)
Button Dev Kit con contrasto 🔴 errato (via ::part nel shadow DOM)
Button HTML classico con stesso contrasto 🔴 errato (controllo)
C. Form association cross-shadow-root
Verifica se un <form> nel light DOM riceve i valori degli input Dev Kit (che hanno l’<input> reale dentro il shadow DOM). Per gli utenti, è la differenza tra “il form funziona” e “il form invia dati vuoti”.
Compilare i campi e cliccare “Invia form” — se il riquadro mostra i dati, la form association funziona.
Form Dev Kit dentro form nativo
Clicca "Invia form" per verificare i dati ricevuti dal form nativo.
Form HTML classico (🟢 controllo)
Clicca "Invia form classico" per verificare i dati.
D. ARIA relationships cross-shadow-root
Per spec W3C, aria-describedby e aria-labelledby non funzionano attraverso i confini del shadow DOM: un ID nel light DOM non è risolvibile da un elemento nel shadow DOM.
Dev Kit espone it-aria-describedby e it-aria-labelledby che vengono applicati all’input generato nel shadow DOM. Il test verifica se il riferimento cross-shadow-root funziona in pratica.
Risultato atteso: non funziona (verificato con VoiceOver). Dev Kit fornisce alternative interne (support-text, validity-message) per i casi d’uso standard.
Input Dev Kit con aria-describedby che punta a ID esterno (🔴 errore atteso)
Questa descrizione è nel light DOM, fuori dal web component.
Input HTML classico con aria-describedby (🟢 controllo — deve funzionare)
Questa descrizione è nel light DOM.
Input Dev Kit con aria-labelledby che punta a ID esterno (🔴 errore atteso)
Etichetta esterna nel light DOM
Input HTML classico con aria-labelledby (🟢 controllo — deve funzionare)
Etichetta esterna nel light DOM
E. Focus management
Verifica l’ordine di tabulazione attraverso shadow DOM boundaries.
Posizionarsi sul link “1. Link nativo” e premere Tab ripetutamente. L’ordine atteso è 1→2→3→4→5→6. Shift+Tab per l’ordine inverso.
F. Modal: focus trap e ARIA
Verifica che la modal intrappoli il focus e che gli attributi ARIA siano impostati correttamente.
Aprire la modal, premere Tab ripetutamente — il focus deve ciclare solo tra gli elementi interni. Premere Escape — la modal si chiude e il focus torna sul trigger.
Modal con focus trap
Aprire la modal, premere Tab ripetutamente. Il focus deve ciclare solo tra gli elementi interni della modale. Premere Escape — la modal deve chiudersi e il focus tornare sul trigger.
Modal con form (form association dentro modal)
G. Gerarchia heading mista light DOM + shadow DOM
Verifica se i tool vedono la gerarchia heading completa quando heading nativi e heading nel shadow DOM sono mischiati.
Nota sulla struttura di questa sezione: contrariamente alle altre, qui usiamo deliberatamente heading di livello non convenzionale (h1 nel corpo della pagina) per costruire i casi di test sulla gerarchia. Gli h1 ripetuti e i salti h1→h3 sono parte del test stesso, non errori di impaginazione della pagina. I tool che calcolano la struttura heading dovrebbero segnalarli.
Gerarchia corretta (🟢 controllo)
Sezione con heading nativo h2
Gerarchia con salto h1 > h3 (🔴 errore intenzionale)
(test)
Heading nativo dopo heading shadow DOM
(test)
Il callout genera un h2. Il prossimo heading nativo è un h3 — la gerarchia è corretta?
Heading h3 nativo dopo callout h2 shadow DOM
I tool vedono la sequenza h2 (shadow DOM) → h3 (nativo) come gerarchia valida?