Next Level Accessibility: 5 Ways I Made the freeCodeCamp Guide More Usable for People with Disabilities

Accessibilité de niveau supérieur : 5 façons dont j'ai rendu le guide freeCodeCamp plus utilisable pour les personnes handicapées

J'ai passé la majorité du Hacktoberfest 2017 à travailler avec des gens formidables chez freeCodeCamp . Mon objectif était spécifiquement d'aider à amener l'accessibilité de leur site Guide au niveau supérieur.

La première fois que j'ai vu le site, je savais que ce serait une ressource fantastique pour beaucoup de gens, alors j'ai relevé le défi de m'assurer que sa convivialité était de premier ordre pour tout le monde !

Travailler sur le site était également très amusant car il est construit avec React , ce qui a apporté quelques défis de codage supplémentaires en cours de route.

Voyons ensemble les 5 problèmes que j'ai trouvés et comment je les ai résolus !

L'une des premières choses que je vérifie sur un site est s'il y a un lien de saut de navigation disponible. Les liens de saut de navigation sont une fonctionnalité petite mais pratique pour tout site à avoir pour les utilisateurs de clavier uniquement ou de lecteur d'écran. Pourquoi?

Le problème

Sans lien de saut de navigation, les personnes utilisant uniquement le clavier pour Tab devraient parcourir chaque lien de la barre latérale chaque fois que la page se recharge. Comme il y a beaucoup de liens disponibles, naviguer dans cette section serait fastidieux.

La solution

La mise en œuvre d'un lien de saut de navigation est assez simple. C'est généralement le premier élément du DOM (Document Object Model) et au clic, le focus du clavier est envoyé à l'élément de page qui contient le contenu principal de la page.

Le lien que j'ai ajouté a été codé comme suit :

 <a className="skip-link sr-only sr-only-focusable" href="#main"> Skip to main content </a>

La valeur #main dans l'attribut href envoie le focus clavier à l'élément de page qui comporte l'attribut id="main" .

Pour que cet élément de page reçoive le focus du clavier, j'avais besoin d'ajouter un attribut tabindex au conteneur :

 <main className="main" id="main" tabIndex="-1"> { props.children() } </main>

L'ajout de la valeur tabindex de -1 permet à un élément non focalisable de recevoir le focus par programmation, mais est laissé en dehors de l'ordre de tabulation naturel.

Le résultat

Avec la navigation par saut en place, les personnes utilisant un clavier peuvent ignorer des régions répétées comme la zone de navigation latérale pour accéder facilement à la section de contenu principale.

GIF animé présentant le lien de saut au contenu qui n'est visible que lors de la mise au point.

Découvrez le changement de code complet dans le PR (Pull Request): Ajout du lien de saut #4175 .

Amélioration de l'accessibilité n° 2 : étiquette manquante dans le champ de recherche

J'ai remarqué qu'il manquait une label dans le champ de input de la recherche. Avoir une label associée pour chaque input de formulaire est la clé d'une expérience utilisateur réussie. Pourquoi?

Le problème

Lorsqu'il manque une label aux champs de input , les lecteurs d'écran ne sont pas en mesure de décrire avec précision l'objectif du champ. Imaginez un instant un lien sans texte ; à quoi sert ce lien ?

La solution

Celui-ci était assez simple. Ajouter une label à une input consiste à créer l'élément label avec un attribut for , puis à l'associer à une input avec un id .

Afin de ne pas perturber la conception actuelle du site, j'ai également ajouté le prop srOnly pour que l' label soit masquée visuellement.

L' label était codée comme suit :

 <ControlLabel htmlFor="searchInput" srOnly={ true }> Search </ControlLabel>

Ensuite, pour le contrôle input existant, j'ai simplement ajouté la id='searchInput' .

Le résultat

Désormais, lorsque les utilisateurs de lecteurs d'écran accèdent au champ de recherche, ils entendent la valeur de l' label "recherche" et ont plus de contexte sur ce qui est attendu.

Capture d'écran du contrôle de recherche après l'ajout du libellé ; aucun changement visuel!

Découvrez le changement de code complet dans le PR : Search input a11y updates #4123 .

Amélioration de l'accessibilité n° 3 : ajustements des rôles dans la barre latérale

Lors de l'inspection de la source HTML, j'ai remarqué que certains des éléments de la barre latérale comportaient de manière incorrecte des attributs role="presentation" . J'ai également remarqué que certains éléments étaient marqués comme div s au lieu d'un balisage sémantique approprié. Cela nécessitait quelques ajustements. Pourquoi?

Le problème

Deux problèmes existaient avec cette section du site :

  1. Lorsque vous appliquez role="presentation" sur un élément, cela supprime toute signification sémantique. En d'autres termes, lorsqu'un lecteur d'écran rencontre l'élément, il n'y a aucune annonce significative pour informer l'utilisateur à quoi sert l'élément. Imaginez un lien sur une page, mais son texte est de la même couleur que le texte du contenu et sans soulignement. Comment sauriez-vous qu'il s'agissait d'un lien ?
  2. L'autre problème ici est lorsque les éléments div sont utilisés pour baliser une structure significative. Comme vous le savez peut-être, les éléments div n'ont aucune signification sémantique et sont généralement réservés pour créer une structure sur une page. Dans les cas où ils sont utilisés à la place d'éléments sémantiques natifs, vous devez appliquer l'attribut de role approprié pour transmettre cette signification.

La solution

  1. Pour chaque élément et lien de la liste de navigation, j'ai simplement supprimé le role prop afin de permettre à la signification sémantique de transparaître pour les utilisateurs de lecteurs d'écran.
  2. Pour les composants dynamiques qui ont généré des éléments div , j'ai appliqué les accessoires de role appropriés, y compris role="list" pour le composant PanelGroup et role="listitem" pour toutes les instances du composant Panel .

Le résultat

Une fois les accessoires de role ajustés, les utilisateurs de lecteurs d'écran entendront des annonces claires et précises lorsqu'ils rencontreront ces éléments, notamment :

  • Les instances du composant Link seront annoncées comme un élément "link" — très important, et ;
  • Les éléments des composants PanelGroup et Panel seront annoncés comme un élément "liste" . En conséquence, le nombre total d'articles sera également annoncé, donnant le contexte du nombre d'articles disponibles sur le voyage à venir.

Capture d'écran de la barre latérale après les ajustements des attributs de rôle ; aucun changement visuel!

Découvrez le changement de code complet dans le PR : Side nav a11y updates #4093 .

Amélioration de l'accessibilité n° 4 : disponibilité des résultats de recherche non annoncée

En tant qu'utilisateur voyant, j'étais conscient du succès d'une recherche car la zone de contenu principale changeait de contenu pour présenter une liste d'éléments. Mais qu'en est-il d'un utilisateur aveugle de lecteur d'écran ?

Le problème

Si un utilisateur de lecteur d'écran saisissait le texte de recherche et appuyait sur Enter , rien ne serait annoncé indiquant une recherche réussie ou des résultats. Comment savoir quand des articles sont disponibles afin d'avancer et de découvrir ce nouveau contenu ?

La solution

Pour que le nombre de résultats actuel soit annoncé, j'ai créé une nouvelle région aria-live , visuellement cachée. Cette région est peuplée de nouveau contenu lorsque de nouveaux résultats de recherche sont présents.

La région est balisée à l'aide d'un div avec quelques attributs supplémentaires :

  • aria-live="polite" crée la région "live" et indique aux lecteurs d'écran d'attendre que les autres processus soient terminés avant d'annoncer son contenu.
  • aria-atomic="true" indique aux lecteurs d'écran d'annoncer tout le texte de la région, pas seulement le texte modifié.
  • role="status" définit l'attente pour les lecteurs d'écran d'interpréter le contenu en direct comme des informations "consultatives". En d'autres termes, c'est assez important, mais pas critique (car les gens pourraient naviguer et découvrir du contenu par eux-mêmes.)

Voici à quoi ressemble l'extrait de code final :

 <div aria-atomic="true" aria-live="polite" className="sr-only" role="status"> {`${results.length} result${results.length === 1 ? '' : 's'} found`} </div>

Notez l'utilisation du littéral de modèle ES6 pour interpoler le contenu ainsi que pour exécuter une instruction conditionnelle ternaire pour ajuster un état pluriel ou singulier.

Le résultat

Désormais, avec un lecteur d'écran actif, après avoir soumis un terme de recherche, le nombre de résultats sera annoncé par une technologie d'assistance : "20 résultats trouvés !"

Capture d'écran des résultats de la recherche après l'ajout de la région en direct ; aucun changement visuel!

Découvrez le changement de code complet dans le PR : Annonces de résultats de recherche #5137 .

J'ai remarqué lors de la navigation avec un clavier, après avoir cliqué sur un lien pour charger le contenu de la page, l'indicateur de focus restait sur l'élément en cours. C'était un problème. Pourquoi?

Le problème

Sans une gestion appropriée de la mise au point, les utilisateurs de clavier uniquement ou de lecteur d'écran devraient naviguer dans toute la barre latérale de navigation pour accéder au contenu de la page. Non seulement cela, il n'y a pas non plus d'annonce audible alertant l'utilisateur que quelque chose s'est produit sur l'événement click() .

La solution

Le correctif que j'ai fini par utiliser était un peu un hack. Normalement, vous devez créer un accessoire ref sur le conteneur de contenu, puis passer l'objet ref de haut en bas au composant qui génère les éléments de lien de la barre latérale, puis définir focus() sur le conteneur sur click() . Ce n'était pas une solution possible car le site utilisait quelque chose appelé Gatsby et il y avait un problème avec le passage d'objets aux composants Link ? Je ne suis pas vraiment sûr du problème, mais il n'a tout simplement pas coopéré.

Pour contourner cette limitation, ma solution est la suivante :

  1. J'ai ajouté un data-navitem="true" à chacun des composants Link de la barre latérale appropriés.
  2. Sur l'événement click() , le composant Article se charge avec le contenu demandé, en définissant document.activeElement sur l'élément de lien cliqué.
  3. Dans la méthode componentWillMount() du composant Article , je vérifie si l'élément actuellement ciblé (le lien de la barre latérale via document.activeElement) possède l'attribut data-navitem .
  4. Si cette condition est true , déplacez le focus du clavier vers l'élément article .

Le résultat

Désormais, lorsqu'une personne utilisant le clavier active l'un des liens de sous-navigation à partir de la barre latérale, le focus du clavier se déplace vers le conteneur de contenu de l' article . Et cela fournit également un contexte aux utilisateurs de lecteurs d'écran, indiquant que quelque chose s'est passé sur click() .

GIF animé présentant la gestion de la mise au point sur l'article en cliquant sur le lien de la barre latérale.

Découvrez le changement de code complet dans le PR: NavItem focus #7818 .


Et là, nous l'avons! Avec ces quelques ajustements, l'accessibilité et la convivialité du site freeCodeCamp Guide ont bien augmenté ! Les gens peuvent utiliser le site plus confortablement avec facilité et succès.

Ceci est juste un aperçu de haut niveau de quelques problèmes que j'ai abordés, mais je sais qu'il y a plus à faire. Tout le monde sur le repo freeCodeCamp Guide était très sympathique et désireux d'aider à répondre à mes questions de débutant sur React, alors n'hésitez pas si vous voulez aider !

Bon piratage ! 💻😄💖

Retour au blog