Skip to Content

Chapitre 11.4 — Les librairies accessibles

⏱️ TL;DR — Les composants complexes (modale, menu, combobox, onglets) sont difficiles à rendre accessibles à la main. La bonne nouvelle : des librairies « headless »Radix UI, React Aria (Adobe), Headless UI, Ariakit — implémentent pour toi les patterns APG (focus, clavier, ARIA) et te laissent 100 % du style. Ne réinvente pas un combobox accessible : utilise une base éprouvée, puis teste quand même. Côté Next.js, next/link rend un vrai <a> et next/image impose un alt.

🎯 Objectifs

  • Savoir ce qu’est une librairie headless et pourquoi elle aide l’accessibilité.
  • Choisir entre Radix UI, React Aria, Headless UI, Ariakit.
  • Utiliser correctement next/link et next/image.
  • Comprendre qu’une lib ne dispense pas de tester.

Le problème que résolvent ces librairies

Reprends le combobox : rôles ARIA, aria-activedescendant, gestion des flèches, annonces, sélection… des dizaines de détails, chacun source de bug. Réécrire ça à chaque projet est déraisonnable. Les librairies headless (sans style) encapsulent tout ce comportement — focus, clavier, ARIA, gestion des états — et exposent des composants non stylés que tu habilles librement (Tailwind, CSS Modules, ce que tu veux).

Tu récupères donc l’accessibilité éprouvée et la liberté de design. C’est le meilleur des deux mondes pour les composants complexes.

// Exemple : une modale accessible avec Radix (focus piégé, Échap, aria gérés) import * as Dialog from '@radix-ui/react-dialog' function ConfirmDialog() { return ( <Dialog.Root> <Dialog.Trigger className="btn">Quitter le cours</Dialog.Trigger> <Dialog.Portal> <Dialog.Overlay className="overlay" /> <Dialog.Content className="modal"> <Dialog.Title>Quitter le cours ?</Dialog.Title> <Dialog.Description>Ta progression est enregistrée.</Dialog.Description> <Dialog.Close className="btn">Annuler</Dialog.Close> </Dialog.Content> </Dialog.Portal> </Dialog.Root> ) }

Ici, le piège de focus, la fermeture par Échap, le retour du focus au déclencheur, role="dialog", aria-modal, l’association titre/description : tout est géré par la lib.

Le paysage des librairies

LibrairieQuiPoints forts
Radix UIWorkOSPrimitives non stylées, très populaires (base de shadcn/ui), API claire
React AriaAdobeHooks bas niveau très rigoureux, i18n, gestion tactile/pointeur poussée
Headless UITailwind LabsSimple, s’intègre bien à Tailwind, moins de composants
AriakitcommunautéLarge couverture de patterns, flexible

💡 Réflexe — Utilise une lib headless pour les composants complexes (modale, menu, combobox, onglets, popover) où l’accessibilité est difficile. Pour un simple bouton ou un lien, reste sur le HTML natif (3.4) : pas besoin d’une lib pour un <button>. La règle « préférer le natif » vaut toujours ; les libs prennent le relais là où le natif n’existe pas.

  • next/link rend un vrai élément <a> : la navigation reste sémantique et clavier-accessible. Ne le transforme pas en <div onClick>. Le texte du lien doit être explicite (« Voir le cours React », pas « Cliquer ici »).
  • next/image impose la prop alt (l’oublier est une erreur de build/lint) : mets un alt descriptif, ou alt="" si l’image est décorative — voir les alternatives textuelles.
import Image from 'next/image' import Link from 'next/link' <Link href="/cours/react">Voir le cours React</Link> <Image src="/diplome.png" width={320} height={200} alt="Certificat de fin de formation" /> <Image src="/decor.svg" width={40} height={40} alt="" /> {/* décoratif */}

⚠️ Piège — Croire qu’une librairie accessible rend ton appli accessible « automatiquement ». Elle rend le composant accessible, si tu l’utilises correctement (fournir les titres, les labels, ne pas casser sa structure). Le reste — ordre des titres, contraste, contenu des alt, gestion du focus au changement de route — reste ta responsabilité. Une lib est un point de départ, pas une garantie.

🧭 Sur A11yLearn — Pour A11yLearn, on adopte Radix pour la modale « quitter le cours », le menu du compte et les onglets du tableau de bord : trois composants qui auraient demandé des centaines de lignes d’ARIA et de gestion clavier. On garde en revanche des <button> et <a> natifs partout ailleurs. Et on teste chaque composant au clavier et au lecteur d’écran malgré la lib.

✏️ Exercices

Exercice 1 — Lib ou natif ? Pour chacun, dis si tu utiliserais une lib headless ou du HTML natif : (a) un bouton « S’inscrire », (b) une modale de confirmation, (c) un lien vers un cours, (d) un combobox de recherche avec autocomplétion.

✅ Solution

(a) Natif (<button>). (b) Lib (le piège de focus et la gestion d’Échap sont difficiles à faire parfaitement à la main). (c) Natif (next/link<a>). (d) Lib (le combobox est le pattern le plus complexe — réinventer son ARIA et son clavier est très risqué). Règle : natif pour le simple, lib pour le complexe.

Exercice 2 — L’alt de next/image. Un collègue met alt="image" partout pour faire taire le lint. Pourquoi est-ce mauvais, et que proposer ?

✅ Solution

alt="image" satisfait le lint mais dégrade l’accessibilité : le lecteur d’écran annonce « image, image », bruit inutile. Il faut soit un alt descriptif de l’information portée (« Certificat de fin de formation »), soit alt="" (vide) si l’image est purement décorative — ce qui la retire de l’arbre d’accessibilité. Le but n’est pas de remplir la prop, c’est de fournir la bonne alternative.

🧠 Quiz de révision

1. Qu’est-ce qu’une librairie « headless » ?

Une librairie qui fournit le comportement accessible d’un composant (focus, clavier, ARIA, états) sans style : tu habilles toi-même. Tu récupères l’accessibilité éprouvée tout en gardant la liberté totale de design.

2. Cite deux librairies accessibles pour React.

Parmi : Radix UI, React Aria (Adobe), Headless UI (Tailwind Labs), Ariakit. Elles implémentent les patterns APG (modale, menu, combobox, onglets…).

3. Pour un simple bouton, faut-il une lib ?

Non. Le HTML natif <button> suffit et apporte rôle, focus et clavier gratuitement. Les libs sont utiles pour les composants complexes que le natif ne couvre pas.

4. Que garantit next/image côté accessibilité ?

Elle impose la prop alt (l’oublier casse le lint/build). Mais c’est à toi de fournir un alt pertinent (descriptif) ou alt="" pour une image décorative — la prop obligatoire ne juge pas du contenu.

5. Une lib accessible suffit-elle à rendre l’appli accessible ?

Non. Elle rend le composant accessible si bien utilisé, mais la structure des titres, le contraste, le contenu des alt, le focus au changement de route et le contenu global restent ta responsabilité. Il faut toujours tester.


Chapitre suivant : Pièges Next.js — les erreurs spécifiques à surveiller dans une appli Next.js.

Last updated on