Composants d'interface riche et accessibilité

Sébastien (@sdussaut)

Développer des composants d'interface riche (onglets, accordéons, overlays,…) sont probablement une des tâches les plus récurrentes en développement front. Si certaines sont assez triviales (les onglets par exemple), d'autres peuvent se révéler beaucoup plus exigeantes (comme les overlays).
Cet état de fait a permis l'émergence de nombreux plugins et bibliothèques diverses et variées pour nous faciliter la tâche.
Seulement voilà : ces plugins reposent le plus souvent sur une dépendance plus importante (comme jQuery) et ne proposent pas toujours un bon niveau d'accessibilité.

Partant de ce constat, fin 2016, nous avons commencé à développer, pour nos besoins d'abord, quelques composants d'interface sans dépendance extérieure et avec un bon niveau d'accessibilité. 

Droit au but

Chez Switch, on ne va pas se le cacher, on préfèrera toujours l'emploi de quelques composants spécialisés répondant à un besoin spécifique plutôt qu'une grosse bibliothèque générique qui fait tout y compris ce dont on n'a pas besoin.
L'emploi du JS vanilla est par essence une seconde nature et la difficulté à trouver des composants riches sans dépendance nous a poussé à les écrire. Mais pas tous seuls dans notre coin.

Quitte à écrire des modules from scratch, autant essayer de pousser la chose et de les écrire directement accessibles. Pour cela, on s'est appuyé sur les compétences de nos amis de chez Atalan afin de valider les comportements des modules : interactions clavier, prise de focus, etc tout en se reposant sur leurs notices AcceDe Web pour les règles et usages courants.

Le renouveau

Après cette première version fin 2016, le travail a repris et nous proposons aujourd'hui une deuxième itération de nos modules qui suit la nouvelle version des recommandations WCAG 2.1.

Les changements principaux sont les suivants :

  • les modules accordéon et onglets ont été séparés en deux modules distincts
  • un module d’overlay a été ajouté
  • le code a été en grande partie réécrit pour une meilleure maintenance et flexibilité
  • les tests unitaires ont été améliorés

Accordéons et onglets

Ces deux modules ont été en partie réécrits notamment parce que la spécification a évolué : si avant les accordéons faisaient partie intégrante de la spécification Tablist, ce n'est plus le cas aujourd'hui. Seuls les onglets en font partie.
Onglets et accordéons ayant de fait beaucoup moins de choses en commun, les conserver au sein du même module n'était plus vraiment pertinent.
En outre, leur séparation permet également aux développeurs utilisant nos scripts de n'importer que ce dont ils ont réellement besoin, ce qui participe à la propreté du code.

Overlay

Un nouveau script fait son apparition avec cette nouvelle version : les overlays. Par overlays, nous entendons les éléments qui passent par dessus un site comme les popins, bandeaux de notifications, etc.
Les overlays sont de manière générale plus complexes à gérer que des onglets. Et notamment lorsqu'on cherche à atteindre un bon niveau d'accessibilité.

Ce script permet de gérer les deux grands types d’overlay dialog et alertDialog (ainsi que les overlays simples, sans attribut role). Leur différence est assez claire : alertDialog attend une action utilisateur obligatoire et ne peut pas être fermé tant que cette action n'a pas été réalisée. Exemple : prendre connaissance de nouvelles conditions générales pour un service, renseigner une information manquante pour un compte utilisateur, etc. Il ne pourra donc pas être fermé par la touche echap ou un clic sur le voile d'opacité l'entourant.
dialog à l'inverse représente une popin au sens le plus commun du terme : un contenu supplémentaire s'affichant par dessus la page courante mais qu'il est possible de fermer comme on le souhaite.

Le script permet également d'instancier un overlay de deux façons distinctes afin de couvrir le plus de cas possibles : en lui passant uniquement son contenu (le script prenant en charge la création de la racine de l’overlay) ou en lui passant un overlay complet. Ce sera alors à l'utilisateur de renseigner les différents attributs aria-*.

Enfin, tout comme les deux autres modules, ce script n'anticipera pas les comportements annexes : animations d'ouverture/fermeture, gestion du défilement de la page. À la place, le script met simplement en place des hooks afin que le développeur puisse gérer ces comportements en fonction du cycle de vie du module.

Tout est décrit dans la documentation sur a11y.switch.paris

Réécriture du code

Le code des modules a été en grande partie revu. Ainsi, tout a été réécrit en ES6 pour plus de lisibilité et profiter des nouvelles avancées de JavaScript.
En conséquence, le dépôt de source propose maintenant diverses versions des scripts : une version ES6 à importer (et transpiler éventuellement) directement dans une base de code mais également une version transpilée en ES5 pour les codebases ne disposant pas encore d'ES6. Enfin, la version ES5 est également proposée en version minifiée.

Le tout est disponible sur le dépôt Github du projet et installable via NPM.

Tests unitaires

Le projet disposait déjà de tests unitaires que nous avions écrits pour la première version des modules. À l'époque, ils étaient basés sur Tape pour le framework de test et sur NightmareJS pour l'environnement d'exécution.
Pour cette nouvelle version, nous avons conservé Tape (qu'on apprécie pour sa simplicité et sa lisibilité) mais nous avons basculé sur Puppeteer pour l'environnement.

Puppeteer fournit un environnement de test plus proche de la réalité, en proposant de piloter Chrome en mode headless, que NightmareJS, qui lui propose electron.

Enfin, de nouveaux tests ont également été ajoutés pour coller à la nouvelle spécification alors que d'autres ont été retirés car devenus obsolètes.

Et après ?

Le projet continue, avec d'autres modules à venir et la maintenance des existants.
Si ce projet vous est utile, si vous avez des questions, venez en discuter avec nous sur Twitter :-)

Si vous rencontrez des bugs ou que nous avons omis certains cas d'usage, n'hésitez surtout pas à ouvrir un ticket sur Github :

Quelques liens