Dezvoltarea unei aplicații web complexe, precum Fonoteca Pontes, pentru utilizatorii de screen reader este o călătorie fascinantă. Când am pornit la drum, foloseam Angular Material, o librărie excelentă, dar care, pe ecrane de 360px și utilizată prin VoiceOver sau TalkBack, a scos la iveală provocări neașteptate. Accesibilitatea (a11y) nu este doar un checkbox în Lighthouse, ci o experiență de utilizare continuă.
Auditul: Dincolo de scorurile Lighthouse
Am început cu axe-core și Lighthouse, dar am realizat rapid că scorul de 100 nu garantează o navigare fluidă. Testarea manuală cu TalkBack pe Android a fost „momentul adevărului”. Am găsit meniuri care „înghițeau” focusul și liste drag-and-drop care erau imposibil de parcurs. Problema principală? Interfața desktop-first nu era gândită pentru fluxul liniar al cititoarelor de ecran.
Gestionarea Focusului cu Angular CDK
Dialogurile modale sunt coșmarul oricărui utilizator de screen reader dacă focusul nu este capturat corect. Folosind cdkTrapFocus, am asigurat o experiență predictibilă în ferestrele de editare playlist:
<div cdkTrapFocus [cdkTrapFocusAutoCapture]="true" class="modal-container">
<h2>Editează Playlist</h2>
<!-- Conținutul formularului -->
</div>
Anunțuri dinamice: Aria-live pentru context
Când un utilizator salvează o melodie, acesta trebuie să primească feedback. Am creat o directivă simplă pentru a gestiona aria-live fără a întrerupe redarea audio:
@Directive({ selector: '[appAnnouncer]' })
export class AnnouncerDirective {
constructor(private el: ElementRef, private renderer: Renderer2) {
this.renderer.setAttribute(this.el.nativeElement, 'aria-live', 'polite');
this.renderer.setAttribute(this.el.nativeElement, 'aria-atomic', 'true');
}
}
Reordonarea listelor: Dincolo de Drag-and-Drop
Gesturile de drag-and-drop sunt adesea inaccesibile. În Fonoteca Pontes, am adăugat butoane explicite de “Mută sus” și “Mută jos”, gestionate prin FocusKeyManager pentru a menține focusul utilizatorului vizibil în timpul operațiunilor de reordonare.
// Exemplu logică mutare item
moveItem(index: number, direction: 'up' | 'down') {
const newIndex = direction === 'up' ? index - 1 : index + 1;
moveItemInArray(this.playlist, index, newIndex);
this.announceChange(`Melodie mutată ${direction === 'up' ? 'sus' : 'jos'}`);
}
Reducerea zgomotului vizual
Am curățat ierarhia de heading-uri (<h1> la <h6>) pentru a permite utilizatorilor să sară rapid între secțiuni. Elementele decorative au primit aria-hidden="true", iar link-urile de “Sari la conținut” au devenit obligatorii pentru a evita parcurgerea repetitivă a meniului de navigare pe mobil.
Feedback-ul real: Iterația finală
După ce am implementat aceste schimbări, am invitat doi utilizatori de screen reader să testeze aplicația. Feedback-ul lor a fost neprețuit: „Acum pot naviga în 5 secunde, înainte îmi lua un minut”.
Pentru testarea automată a acestor fluxuri, recomand Testing Library:
it('afișează butonul de editare cu rolul corect', () => {
render(PlaylistComponent);
const btn = screen.getByRole('button', { name: /editează/i });
expect(btn).toBeInTheDocument();
});
Accesibilitatea nu este o destinație, ci un proces de învățare continuă. Începeți prin a asculta aplicația voastră prin TalkBack sau VoiceOver – veți descoperi o perspectivă nouă care va îmbunătăți experiența tuturor utilizatorilor.

