
Comment nous avons rendu Yandex Cloud plus accessible avec le système de design Gravity UI
Comment nous avons rendu Yandex Cloud plus accessible avec le système de design Gravity UI
Bonjour, je m’appelle Vova Timofeïev et je suis chef de projets techniques chez Yandex Cloud. Dans cet article, je vais expliquer comment nous avons rendu le site de la plateforme cloud plus accessible, combien d’itérations nous avons traversées et quel rôle Gravity UI a joué dans ce processus.
La base de l’accessibilité de tous les services, c’est la qualité de leur prise en charge des lecteurs d’écran (screen readers). Grâce à ces programmes, les personnes en situation de handicap perçoivent l’interface et interagissent avec elle.
Les sites web ne font pas exception. Nous devions donc déterminer dans quelle mesure Yandex Cloud est accessible à toutes et à tous.
Chez Yandex, nous entendons par accessibilité le fait que nos services doivent pouvoir être utilisés confortablement par chacun, indépendamment de limitations physiques temporaires ou permanentes. Par exemple, 16 services de Yandex sont actuellement adaptés pour les utilisateurs aveugles: Lavka, Go, Search, Browser, Mail et d’autres. Une équipe de tests non visuels aide à améliorer l’accessibilité de chaque service — et dans le cas dont je parle dans cet article, nous n’aurions pas pu nous en passer non plus.
Spoiler: à l’issue des tests, plusieurs points discutables lors de l’utilisation des lecteurs d’écran ont été détectés — ils se sont transformés en tâches concrètes.
Mais reprenons dans l’ordre.
Tout a commencé avec Gravity UI
Gravity UI est un système de design et une bibliothèque de composants sur laquelle s’appuient le site de Yandex Cloud et des dizaines d’autres produits du cloud. Elle est publiée en open source et accessible à tous (nous sommes ravis de constater que l’activité dans le chat de la communauté a nettement augmenté au cours des six derniers mois).
Ce que nous avons:
- un ensemble de composants React de base;
- une bibliothèque/constructeur pour les landing pages;
- des guides détaillés rédigés par les designers sur l’utilisation des composants;
- une bibliothèque dans Figma;
- un pack de près de 600 icônes prêtes à l’emploi;
- ChartKit — un package de visualisation de données;
- Yagr — un rendu de graphiques haute performance basé sur uPlot;
- i18n — un package de localisation d’interface;
- d’autres bibliothèques utiles.
En mars 2024 est sortie une mise à jour de la bibliothèque clé: UIKit v6. Elle apporte une mise à jour du composant List, la prise en charge du paramètre RTL dans tous les composants, ainsi qu’un ensemble d’améliorations a11y pour renforcer l’accessibilité.
Quoi de neuf dans UIKit v6
-
Composant List 2.0. Au départ, UIKit avait un composant List, mais nous voulions l’améliorer sur certains points. En collectant les demandes, nous avons établi la liste suivante:
- prise en charge de différentes tailles et largeurs;
- icône sur l’élément de liste, nombre et position d’icônes variables;
- prise en charge des états;
- contenus différents dans les éléments (une ligne, plusieurs lignes ou liste d’utilisateurs);
- prise en charge de différents séparateurs et de la mise en groupes.
Ce sont des changements majeurs, c’est pourquoi nous avons créé List 2.0. Pour l’instant elle est publiée en version prestable, mais nous recommandons aux utilisateurs de migrer vers elle et de nous faire des retours.
-
RTL. Si vos applications ou sites doivent s’afficher en hébreu, en arabe ou dans d’autres langues écrites de droite à gauche, vous avez besoin du support des standards RTL. En RTL:
- un mot inséré en alphabet latin s’écrit de gauche à droite;
- les chiffres s’écrivent de gauche à droite;
- la ponctuation en arabe s’écrit également de gauche à droite, etc.
Nous avons pris en charge le paramètre RTL dans tous les composants. Pour avoir un exemple complet sous la main, nous avons créé une page de démonstration en arabe. Vous pouvez voir l’implémentation dans le code source de landing. Il y a aussi des exemples dans le storybook.
-
Accessibilité (a11y):
- ajout du plugin eslint au projet;
- prise en charge du clavier pour les états clickable et closable du composant Persona;
- désactivation de onClick sur 15 composants non interactifs;
- prise en charge du clavier dans le composant SelectionTable.
Comment nous en sommes arrivés aux améliorations a11y
L’équipe de tests non visuels et son responsable, Anatoli Popko, nous ont beaucoup aidés. Lors d’une réunion, Anatoli a testé pas à pas la sandbox et le site de Gravity UI afin de comprendre quels problèmes d’accessibilité existaient à ce moment-là.
Nous avons vérifié l’accessibilité des composants en nous déplaçant sur le site à l’aide du clavier et de commandes spécifiques aux lecteurs d’écran.
Visuellement, cela ressemblait à ceci:

Après la réunion, l’équipe a reçu des tâches concrètes et, sur GitHub, trois nouveaux issues ont été créés concernant les composants de base.
Plus de détails:
- Dans la liste déroulante, le second niveau d’éléments
ne s’ouvre pas
au clavier — uniquement via un clic de souris.

-
Il n’est pas clair quel élément d’une liste à puces en markdown est sélectionné dans le composant Select.
-
Les boutons sans libellés textuels, uniquement indiqués graphiquement, sont lus comme « bouton » ou « bouton radio “. Ce bug n’apparaît que sur la landing page; le composant lui-même prend en charge aria-label, mais nous ne l’avons pas utilisé.

Au final, nous avons compris que, puisque nous n’avons pas trouvé des dizaines de remarques, l’accessibilité de la bibliothèque est déjà à un bon niveau. Tester des composants hors contexte réel est très difficile; c’est pourquoi nous avons décidé de commencer par vérifier l’accessibilité d’un produit finalisé. Cela nous a permis d’identifier des améliorations a11y supplémentaires.
Accessibilité de Yandex Cloud
Inspirés par la mise à jour de Gravity UI, nous avons décidé de tester l’accessibilité de nos services: commencer par le site Yandex Cloud, puis étendre cette expérience à d’autres interfaces.
Il existe un ensemble de standards permettant d’atteindre l’accessibilité. Mais pour tester de manière fiable les interfaces de Yandex Cloud et mieux comprendre à quel point notre site est pratique pour tous, nous avons réalisé un audit.
Audit d’accessibilité
Nous nous sommes de nouveau tournés vers nos collègues de l’équipe de tests non visuels, ainsi que vers Anatoli, afin de tester le site ensemble, consigner les problèmes et les prendre en charge. Au total, il y a eu deux itérations espacées d’environ un mois — test puis retest.
Pendant les tests, nous avons relevé tout un ensemble de corrections à implémenter.
Sur la page d’accueil
-
Le contrôle de recherche nécessitait une refonte. Dans notre interface, la recherche est réalisée sous forme d’une zone de recherche avec une icône de loupe. En cliquant dessus, on ouvre le champ de saisie. Dans l’ancienne implémentation, pour le lecteur d’écran, il s’agissait d’éléments indépendants, ce qui perturbait les utilisateurs aveugles.

-
Pour le choix de la langue, nous utilisions l’attribut d’état « replié “, alors qu’il s’agissait en réalité d’un bouton de sélection et non d’une liste déroulante. Il manquait le libellé « langue ‘, et il n’y avait pas d’espace dans « langue — région ‘.
-
Dans le menu du compte, le focus n’était pas piégé: à l’activation, l’utilisateur sortait de la liste des éléments du menu.
-
La balise main était dupliquée sur la page d’accueil: il fallait en supprimer une.
-
Section avec des exemples: il fallait utiliser un onglet (tab) au lieu d’un bouton.

- Dans la carte d’exemple, le texte avait été mis dans aria-describedby, de sorte que le lecteur d’écran ne le lisait qu’une seule fois — ce qui est peu pratique pour étudier des informations importantes. En analysant le bug, nous avons compris qu’il valait mieux procéder à un refactoring complet du composant Card; nous avons créé un issue où l’on peut consulter les détails des changements et participer à la discussion.
Navigation
- Problème de focus: lors du déploiement du premier niveau du menu, il faut déplacer le focus vers le sous-menu.
- Il fallait supprimer TabIndex du premier niveau du menu. La mise en œuvre actuelle entraînait une énumération en double de tous les éléments du menu.
- Il fallait piéger le focus clavier dans la navigation lorsqu’elle est déployée. Sinon, on peut sortir du menu vers la page, puis ne plus pouvoir revenir.
Footer
- Yandex Cloud était enveloppé dans une liste. Les titres des listes de liens dans le footer étaient enveloppés dans un élément de liste, donc NVDA les identifiait comme faisant partie de la liste et relisait deux fois la même liste à l’utilisateur.
- Il manquait des libellés pour les liens vers l’App Store et Google Play. Au moment du test, des fragments d’URL étaient lus, ce qui ne permettait pas à l’utilisateur de comprendre.
Section « Blog ”
- Les boutons « Tous les thèmes » et « Tous les services » n’étaient pas correctement associés. Les boutons de select n’annonçaient pas leur contenu.
- Il fallait une prise en charge de l’accessibilité dans les listes: à l’ouverture d’une liste déroulante, le focus du lecteur d’écran doit basculer vers les éléments de cette liste. En plus, il doit permettre une navigation simplifiée entre les éléments avec les flèches normales — sans utiliser de combinaisons de touches.
Articles du blog
- Il manquait l’élément « Vous êtes ici » dans le fil d’Ariane.
- Il fallait piéger le focus dans le dialogue.
- Le compteur de favoris n’avait pas de nom. Le compteur était un bouton avec une icône et un nombre. Les lecteurs d’écran lisaient le nombre — sans l’icône, il était impossible de comprendre l’action du bouton.
Nous avons regroupé toutes les tâches dans un epic et avons commencé le travail. Pour une partie des tâches, des issues ont été créés sur GitHub.
Je vais détailler les cas les plus intéressants.
Composant Select

Lors des tests, nous avons constaté qu’en navigation au clavier, les noms des éléments de la liste ne sont pas annoncés par le lecteur d’écran. Nous avons pu corriger partiellement le problème grâce à l’attribut aria-activedescendant, mais pas complètement.
Problèmes restants
-
Dans Safari, cette méthode ne fonctionne pas et, pour l’instant, on ne sait pas comment le résoudre.
-
Le filtre de recherche n’est pas toujours pris en charge (en réalité jamais — la prise en charge n’est simplement pas implémentée). Habituellement, aria-activedescendant est appliqué à l’élément principal de la liste déroulante et pointe vers l’élément sélectionné. Actuellement, il est appliqué au bouton qui ouvre la liste déroulante. Lorsqu’on appuie sur les flèches haut/bas, nous changeons sur le bouton la valeur de aria-activedescendant vers l’élément précédent ou suivant. Ainsi, le lecteur d’écran peut lire depuis le bouton quel élément est sélectionné.
Le problème du filtre de recherche est que son champ de saisie n’a pas l’attribut aria-activedescendant. Si une personne met le focus sur le champ du filtre pour saisir du texte, le lecteur d’écran ne peut pas y lire quel élément de la liste est actif, et la navigation par flèches ne fonctionne pas.
-
Les options sélectionnées ne sont pas marquées; il faut leur ajouter un attribut, par exemple aria-selected.
L’issue avec les problèmes actuels est disponible ici.
Fil d’Ariane

Le fil d’Ariane (Breadcrumbs) est un élément de navigation qui montre le chemin de l’utilisateur sur le site. Dans notre cas, le lecteur d’écran lisait tout le chemin, et il était impossible de comprendre dans quelle partie du site la personne se trouve. De plus, tout le composant était présenté comme un simple ensemble de liens.
Nous avons décidé de nous écarter des standards et de résoudre le problème de manière simple et optimale — en ajoutant pour le lecteur d’écran l’étiquette « Vous êtes ici “. Au final, nous avons combiné l’approche standard et l’étiquette.
Au cours du travail, il s’est avéré que pour que cette étiquette soit lue, il faut l’attacher à un élément que les lecteurs d’écran n’ignorent pas. Il était plus simple de l’attacher à une structure conventionnelle que d’inventer un moyen de l’éviter. Cela dit, l’étiquette reste utile: elle aide l’utilisateur à comprendre plus vite qu’il entend bien le fil d’Ariane.
Images sans libellé
Certaines images du site étaient placées sans libellé, et le lecteur d’écran les lisait comme « Image “. Cette information n’apporte rien d’utile et ne permet pas de se représenter l’interface; nous avons donc décidé de masquer au lecteur d’écran les images sans libellé.
Ordre du texte dans les blocs

À plusieurs endroits sur notre site, les informations sont présentées sous forme d’un bloc unique, par exemple une carte d’événement ou une carte d’article dans le blog.
Nous avons remarqué que les lecteurs d’écran lisent les informations dans un ordre différent de celui des utilisateurs voyants. Pour la carte d’événement, le lecteur d’écran lisait ainsi: statut d’inscription, heure, lieu, puis seulement le titre et la description de l’événement.
En général, on ne suit pas un parcours linéaire: on regarde d’abord le titre, puis le sous-titre et l’image. Le problème est que le lecteur d’écran lit les éléments dans l’ordre où ils se trouvent dans le DOM. Pour corriger l’ordre, nous avons dû reconstruire la structure.

Nous avons été surpris, mais pour certaines combinaisons « système d’exploitation — navigateur “, cela n’a pas fonctionné. Par exemple, dans Mozilla Firefox sur macOS, le problème est resté malgré la modification de l’ordre dans le DOM. Espérons que les développeurs de Firefox corrigeront ce comportement dans les nouvelles versions.
Fenêtres modales

Lorsqu’un utilisateur voyant ouvre une fenêtre pop-up dans l’interface, son regard se porte sur le contenu de cette fenêtre. Toutefois, le contenu du site reste accessible, et il peut y revenir si nécessaire.
Lorsque l’on utilise le site avec un lecteur d’écran, la situation change. Si la pop-up n’est pas modale, elle n’a pas de limites. La navigation devient alors plus difficile: on peut sortir de la pop-up par erreur en utilisant la navigation entre éléments.
Il existe un standard pour les fenêtres modales, et si on le suit, il n’est pas obligatoire de piéger toutes les pop-ups de l’interface.
Mais lors des tests, nous sommes arrivés à la conclusion que rendre les pop-ups modales est une bonne pratique qui simplifie l’usage du site avec un lecteur d’écran.
Nous avons décidé de rendre toutes les pop-ups modales, tout en laissant aux utilisateurs la possibilité de configurer un scénario alternatif.
Vous pouvez configurer ce scénario en définissant role="dialog", aria-modal="true". Avec la combinaison VoiceOver + Firefox, cette solution n’est pas prise en charge: les détails figurent dans l’issue fermé ici.
Diplodoc
Portés par notre dynamique, les développeurs de la plateforme de création de documentation technique Diplodoc ont réalisé plusieurs améliorations a11y dans leur produit:
- Ils ont vérifié tous les éléments de syntaxe supplémentaires de YFM (Yandex Flavored Markdown) et les ont réécrits afin qu’ils soient visibles pour les lecteurs d’écran.
- Ils ont amélioré le flux d’utilisation de la documentation au clavier: correction de l’ordre de sélection des éléments et ajout de la possibilité de sélection pour tous les éléments interactifs.
- Ils ont ajouté des libellés et des indications correctes pour les éléments d’interface, ce qui simplifiera nettement l’utilisation du service pour les personnes utilisant des lecteurs d’écran.
Comme nous utilisons Diplodoc pour afficher notre documentation, ces améliorations ont également renforcé l’accessibilité de la documentation sur le site de Yandex Cloud.
Résultats et plans
Nous avons fait les premiers pas pour améliorer l’accessibilité des interfaces de Yandex Cloud pour tous les utilisateurs. Il nous reste à transférer cette expérience vers d’autres interfaces du service et à corriger les problèmes que nous connaissons déjà.
Gravity UI a facilité notre travail sur l’accessibilité, et nous continuons à traiter les issues ouverts avec le tag a11y. Au moment de la rédaction de cet article, nous avions 14 issues ouverts et 24 fermés — vous pouvez les consulter ici.

Nous attendons vos PR et vos commentaires sur l’accessibilité et le fonctionnement des services, ainsi que des exemples d’utilisation de Gravity UI sur vos sites.

Vladimir Timofeïev
Chef de projets techniques chez Yandex Cloud