Conlaccento

Un blog sul web making di Antonio Trifirò

La manopola che non ho fatto: AI e accessibilità in un side project


Mia figlia ha iniziato a studiare batteria, mi ha ispirato e dopo dieci anni ho ripreso a studiarla anche io. Al di là di quella che potrebbe essere una bella storia padre-figlia, la questione da cui parte questo post è che il maestro usava per il dettato ritmico un’applicazione per Windows, datata, con un’interfaccia che sembrava uscita da un altro decennio. Funzionava, eh, ma era il genere di strumento che usi nonostante l’interfaccia, non grazie a lei.

Qualche anno fa avrei pensato “sarebbe bello farne una versione web” e la cosa sarebbe finita lì, schiacciata tra il lavoro e il resto. Questa volta no: con l’AI accanto, il costo di partenza di un side project si è abbassato abbastanza da farmi provare. Ne è uscita Just Another Rhythm Ear Trainer, una web app per il dettato ritmico con un metronomo per batteristi.

Questo post però non è un “guarda cosa ho fatto in un giorno”. È il racconto di cosa ho imparato — soprattutto sull’accessibilità — usando l’AI su un progetto vero, piccolo e mio. Alcune cose hanno funzionato meglio di quanto pensassi, altre mi hanno ricordato che certe decisioni non si delegano.

Cosa fa l’app (in breve)

L’app genera un ritmo, tu lo ascolti e lo trascrivi su carta, poi scopri la soluzione e ti correggi da solo. Niente punteggi, niente livelli: scegli le figure su cui vuoi esercitarti, il tempo, la velocità, e via. Dal menù in alto passi al metronomo, con tap tempo, tempi dispari, volumi separati per le suddivisioni e una scaletta per i concerti. Si installa come app e funziona anche offline.

La prima versione, solo il dettato, era online in giornata. Il metronomo è arrivato un mese dopo. Oggi la usa il mio maestro, e l’ho mandata a qualche amico che suona o studia musica, sperando possa servirgli.

Il primo test vero l’ha fatto il maestro

Nella prima versione ogni nota era il colpo di un rullante. Mi sembrava la scelta ovvia: è un’app per batteristi, no?

Il maestro, usandola, mi ha fatto notare una cosa che a me era sfuggita: il rullante è un suono secco, dura un istante. Una semiminima e una croma suonano uguali, cambia solo lo spazio tra un colpo e l’altro. Ma nel dettato ritmico la durata della nota è proprio l’informazione che devi riconoscere.

La soluzione è stata sostituire il rullante con un LA sintetizzato dal timbro di pianoforte, tenuto per tutta la durata della figura. Adesso una minima suona lunga e una croma suona corta.

Nessun prompt mi avrebbe dato questa correzione: l’AI ha implementato benissimo quello che le avevo chiesto, ma quello che le avevo chiesto era sbagliato. Serviva qualcuno che usasse l’app per il suo scopo reale. È un test di usabilità nel senso più semplice del termine ed è un test che continua ad essere insostituibile anche nell’era dell’AI.

L’accessibilità chiesta subito, non a fine lavoro

Una cosa che ho fatto fin dal primo giorno è stata chiedere l’accessibilità come requisito, non come rifinitura. E qui l’AI mi ha sorpreso in positivo: quando gliela chiedi in modo esplicito, porta a casa parecchie cose che spesso, nei progetti, finiscono in fondo alla lista.

Nello stesso giro di lavoro sono arrivati:

  • gli stili per la modalità a contrasto forzato (quella di Windows), che usa i colori di sistema;
  • una dimensione minima per i pulsanti testuali, così non diventano target troppo piccoli (WCAG 2.5.8);
  • lo scorrimento che segue la nota corrente durante l’ascolto, che diventa istantaneo con prefers-reduced-motion;
  • e un test automatico sul contrasto, che è la cosa di cui voglio parlarti più in dettaglio.

Il contrasto come rete di sicurezza

I colori dell’app vivono tutti in custom properties CSS, per il tema chiaro e per quello scuro. Il test legge quei token direttamente dal file CSS, calcola il rapporto di contrasto con la formula delle WCAG 2 e lo confronta con la soglia giusta per ogni coppia di colori.

Il cuore è una lista di coppie, ognuna con la sua soglia e il suo perché:

/** [foreground, background, minimum ratio, what it is] */
const PAIRS: readonly [string, string, number, string][] = [
  ['text', 'bg', 4.5, 'body text (and inverted legends)'],
  ['muted', 'bg', 4.5, 'secondary text'],
  ['on-primary', 'primary', 4.5, 'main button label (red)'],
  ['on-accent-soft', 'accent-soft', 4.5, 'selected option and hovered button (yellow)'],
  ['highlight', 'bg', 3, 'current note while playing (graphics)'],
  ['border', 'bg', 3, 'control boundaries'],
  // The focus outline has a 3px offset, so it always sits on the page background.
  ['focus', 'bg', 3, 'focus indicator'],
  // ...
];

Quindici coppie in tutto, verificate su entrambi i temi. La cosa che mi piace è che quella lista si legge come una checklist di design: ogni volta che nasce un nuovo accostamento di colori, deve entrare lì, con una soglia e una motivazione.

E il test non è decorativo: ogni push sul ramo principale fa girare i test prima della build, e se un test fallisce il deploy non parte. Un colore che non passa non arriva online.

Il momento in cui questa rete si è vista è stato il cambio di stile. Il test è nato prima che l’app prendesse il suo aspetto attuale, vagamente ispirato al Bauhaus: rosso, giallo e blu pieni su sfondo carta. Con la nuova palette il test è stato aggiornato insieme ai colori, e sono nati token dedicati come --on-primary (il testo sul rosso) e --on-accent-soft (il testo sul giallo). Cambiare stile ha voluto dire, per forza, rispondere alla domanda: questo testo, su questo colore, si legge?

La manopola che non ho fatto

Un mese dopo ho voluto aggiungere un metronomo, e ho provato una strada diversa: ho chiesto a Claude, in chat, di scrivermi un prompt da passare poi all’agente che lavorava sul codice. Il prompt che ne è uscito era dettagliatissimo e chiedeva di replicare le funzioni del Tama Rhythm Watch RW200, un metronomo hardware per batteristi.

Da lì è arrivato di tutto: una manopola rotativa da trascinare in cerchio per regolare il tempo, un display in stile LCD con tanto di retroilluminazione, il silenzio programmato, le scorciatoie per il pedale, perfino il supporto ai pedali MIDI. Tutte cose sensate per l’oggetto fisico. Molte di più di quelle che mi servivano davvero.

È stata la lezione più utile del progetto: se chiedi all’AI di scrivere il prompt, lei riempie il progetto con tutto quello che il suo modello di riferimento sa fare. Non c’è niente di sbagliato nel singolo pezzo; è lo scope che si gonfia. E restringerlo è un lavoro tuo, perché solo tu sai cosa ti serve.

La manopola, poi, è un caso di scuola di accessibilità. Il prompt la voleva accessibile, e descriveva per bene come: role="slider", aria-valuemin, aria-valuemax, aria-valuenow, aria-valuetext, la gestione delle frecce, di PagSu/PagGiù, di Home e Fine… Tutto lavoro da scrivere, testare e mantenere, per ricostruire a mano un controllo che il browser ti dà gratis:

<!-- Native range input: keyboard, focus and screen reader support come for free -->
<input type="range" id="metronome-tempo" min="35" max="250" step="1" />

È la prima regola di ARIA vista dal vivo: se esiste un elemento HTML nativo che fa quello che ti serve, usa quello. Ho scelto lo slider nativo e i controlli standard del web, e ho tenuto le funzioni del metronomo senza la sua forma. Lo skeumorfismo — imitare un oggetto fisico sullo schermo — va bene se ti piace, ma qui complicava l’interazione e l’accessibilità, al di là dei gusti.

Stessa sorte per altre funzionalità proposte: niente volume generale (è fisso al massimo), niente silenzio programmato, niente pedale né MIDI. L’app è più piccola di come l’AI l’avrebbe fatta, ma risponde a ciò che mi serve davvero.

Le lezioni che restano scritte

C’è un’abitudine che ho preso con questo progetto e che mi sta tornando utile anche altrove: quando l’AI sbatte contro un problema, la soluzione non resta nella conversazione ma finisce nel file di istruzioni del progetto (il CLAUDE.md o AGENTS.md), così la volta dopo non si riparte da zero. Alcune di quelle note sono piccole lezioni di accessibilità:

  • l’elemento <output> ha una live region implicita: su uno slider che cambia di continuo, lo screen reader annuncerebbe ogni singolo valore. Lì va messo aria-live="off", e l’annuncio passa da un messaggio di stato che aspetta che il valore si fermi;
  • il layout va verificato a 320 px di larghezza con la spaziatura del testo aumentata (WCAG 1.4.12): è lì che saltano fuori le sbordature;
  • in modalità a contrasto forzato i bordi trasparenti vengono dipinti: vanno resi espliciti.

Sono errori che si fanno una volta. L’importante è non rifarli.

Cosa non ho approfondito (e perché va bene così)

Lo dico chiaramente: su questo progetto non ho approfondito i test di accessibilità come farei su un progetto per un cliente. L’app risponde alle esigenze attuali di chi la usa, ed è un side project: ho scelto consapevolmente dove fermarmi.

E la rete di sicurezza ha i suoi buchi, che conosco:

  • Il test controlla i colori, non le persone. Verifica che le coppie dichiarate passino le soglie; non sa se ho dimenticato una coppia, né come l’app suona davvero con uno screen reader.
  • Usa la formula delle WCAG 2. È quella che conta per la conformità, ma come ho raccontato parlando di APCA e del contrasto, con i colori scuri tende a sovrastimare il contrasto. L’app ha un tema scuro: un test verde lì è una buona notizia, non una garanzia di leggibilità.

Va bene così, a patto di saperlo. Un limite conosciuto è molto meno pericoloso di uno che non sai di avere.

Da non dimenticare, se usi l’AI su un tuo progetto

Alcune domande che credo siano utili all’avvio di un nuovo progetto e che ho imparato da questa esperienza:

  • Hai chiesto l’accessibilità come requisito dal primo prompt, invece di aggiungerla alla fine?
  • Le tue regole di accessibilità sono verificabili da una macchina, ad esempio con un test o un controllo nella pipeline? (Ovviamente non vale per tutti i criteri di successo WCAG.)
  • Un test che fallisce blocca davvero la pubblicazione?
  • Se il prompt l’ha scritto un’AI, hai riletto lo scope e tagliato ciò che non ti serve?
  • Per ogni controllo “speciale” che ti viene proposto, hai cercato prima l’elemento HTML nativo che fa la stessa cosa?
  • Quando l’AI risolve un problema ricorrente, hai scritto la lezione da qualche parte dove la prossima sessione la troverà?
  • Hai fatto provare il risultato a qualcuno che lo usa davvero?
  • Conosci i limiti della tua rete di sicurezza?

Provala

L’app è gratuita e open source (licenza MIT):

Se studi musica e la provi, o se trovi un problema di accessibilità che la mia rete non ha preso, scrivimi: è esattamente il tipo di feedback che la fa migliorare.

Peace&Love! ✌️