Interface utilisateur accessible
Vue d'ensemble
L'accessibilité de l'interface utilisateur de Codexia repose sur la conception de composants conformes RGAA 4.1 niveau AA, garantissant que tous les utilisateurs, quelles que soient leurs capacités, puissent naviguer, comprendre et interagir avec l'application.
Ce document s'appuie sur les principes définis dans specs/design.md et specs/ui.md, en détaillant les exigences d'accessibilité pour chaque composant de l'interface.
Principes d'accessibilité UI
1. Perceptibilité
Contraste des couleurs
- Ratio minimum 4.5:1 pour le texte normal (14-18px)
- Ratio minimum 3:1 pour le texte large (≥ 18px gras ou ≥ 24px)
- Ratio minimum 3:1 pour les composants UI et les éléments graphiques
Avec Radix Colors (cf. specs/design.md) :
/* Conformes WCAG AA */ color: var(--slate-12); /* Texte principal sur fond clair */ background: var(--slate-1); /* Fond principal */ /* Liens et actions */ color: var(--blue-9); /* Ratio ~7:1 sur fond blanc */ /* États */ .success { color: var(--green-9); } /* ~4.8:1 */ .warning { color: var(--amber-11); } /* ~4.6:1, utiliser tone 11 pour amber */ .danger { color: var(--red-9); } /* ~5.2:1 */
Alternatives textuelles
- Tous les éléments non-textuels (images, icônes, graphiques) doivent avoir une alternative textuelle
- Les icônes décoratives doivent être masquées aux lecteurs d'écran (
aria-hidden="true")
Informations par la couleur
- Ne jamais utiliser la couleur comme seul moyen de transmettre une information
- Toujours doubler avec un texte, une icĂ´ne ou un motif visuel
2. Utilisabilité
Navigation clavier
- Tous les éléments interactifs doivent être accessibles au clavier
- Ordre de tabulation logique et cohérent
- Pas de piège clavier (possibilité de sortir de tout élément)
Focus visible
- Outline de 2px sur tous les éléments interactifs (cf.
specs/design.md) - Utiliser
focus-visiblepour distinguer focus clavier du focus souris
/* Focus visible conforme */ :focus-visible { outline: 2px solid var(--blue-8); outline-offset: 2px; border-radius: 4px; } /* Pas de suppression de outline sans alternative */ /* ❌ INTERDIT */ button:focus { outline: none; }
Cibles tactiles
- Taille minimum des zones cliquables : 44Ă—44px (WCAG 2.1 AA)
- Espacement suffisant entre les éléments interactifs
3. Compréhensibilité
Labels et instructions
- Tous les champs de formulaire ont un label visible et associé
- Instructions claires avant les interactions complexes
- Messages d'erreur explicites et liés aux champs concernés
Navigation cohérente
- Menus et navigation identiques sur toutes les pages
- Fil d'Ariane pour indiquer la position dans le site
4. Robustesse
HTML sémantique
- Utilisation des balises natives HTML5
- Structure de document correcte (
<header>,<nav>,<main>,<footer>) - Hiérarchie des titres respectée (h1 → h2 → h3, sans saut)
ARIA utilisé à bon escient
- ARIA uniquement quand le HTML natif ne suffit pas
- Respect des patterns ARIA du W3C
- Tests avec lecteurs d'écran (NVDA, JAWS, VoiceOver)
Composants accessibles
Boutons
<!-- Bouton primaire --> <button type="button" class="btn btn-primary"> Enregistrer </button> <!-- Bouton avec icône --> <button type="button" class="btn btn-secondary"> <svg aria-hidden="true" class="icon">...</svg> <span>Télécharger</span> </button> <!-- Bouton icône seul --> <button type="button" class="btn btn-ghost" aria-label="Fermer"> <svg aria-hidden="true" class="icon-close">...</svg> </button>
Exigences :
- États
:hover,:focus,:active,:disabledbien définis - Contraste suffisant dans tous les états
- Taille minimum 44Ă—44px
- Label explicite (pas de "cliquez ici")
Champs de formulaire
<div class="form-group"> <label for="email" class="form-label"> Adresse email <span class="required" aria-label="obligatoire">*</span> </label> <input type="email" id="email" name="email" class="form-control" aria-describedby="email-help email-error" aria-invalid="false" required /> <small id="email-help" class="form-text"> Nous ne partagerons jamais votre email. </small> <div id="email-error" class="form-error" role="alert" aria-live="polite"> <!-- Message d'erreur inséré dynamiquement --> </div> </div>
Exigences :
- Label visible et associé (
for/id) - Indication visuelle et textuelle des champs obligatoires
- Messages d'aide (
aria-describedby) - Messages d'erreur liés au champ et annoncés (
role="alert") - Validation accessible (pas uniquement par la couleur)
Navigation
<nav aria-label="Navigation principale"> <ul class="nav-list"> <li> <a href="/" class="nav-link" aria-current="page"> <svg aria-hidden="true" class="icon">...</svg> <span>Accueil</span> </a> </li> <li> <a href="/docs" class="nav-link"> <svg aria-hidden="true" class="icon">...</svg> <span>Documentation</span> </a> </li> </ul> </nav> <!-- Fil d'Ariane --> <nav aria-label="Fil d'Ariane"> <ol class="breadcrumb"> <li><a href="/">Accueil</a></li> <li><a href="/docs">Documentation</a></li> <li aria-current="page">Accessibilité</li> </ol> </nav>
Exigences :
- Balise
<nav>avecaria-labeldescriptif - Page courante indiquée avec
aria-current="page" - Ordre de tabulation logique
- Skip links pour navigation rapide
Cartes (Bento Layout)
<article class="card"> <div class="card-header"> <h2 class="card-title"> <svg aria-hidden="true" class="icon">...</svg> Titre de la carte </h2> </div> <div class="card-body"> <p>Description du contenu...</p> </div> <div class="card-footer"> <a href="/details" class="card-link"> En savoir plus <svg aria-hidden="true" class="icon-arrow">...</svg> </a> </div> </article>
Exigences :
- Structure sémantique (
<article>,<h2>, etc.) - Liens explicites (pas de "cliquez ici")
- Icônes décoratives masquées (
aria-hidden="true") - Animation de survol accessible (pas de clignotement > 3 fois/sec)
Tableaux
<table class="data-table"> <caption>Liste des modules Codexia</caption> <thead> <tr> <th scope="col">Module</th> <th scope="col">Statut</th> <th scope="col">Version</th> <th scope="col">Actions</th> </tr> </thead> <tbody> <tr> <td>Core</td> <td> <span class="badge badge-success"> <svg aria-hidden="true" class="icon">...</svg> <span>Stable</span> </span> </td> <td>1.0.0</td> <td> <button type="button" class="btn btn-sm" aria-label="Modifier le module Core"> Modifier </button> </td> </tr> </tbody> </table>
Exigences :
<caption>pour décrire le tableau<th scope="col">ou<th scope="row">pour les en-têtes- Structure
<thead>,<tbody>,<tfoot> - Actions accessibles avec labels explicites
- EntĂŞte sticky accessible (reste dans le flux du document)
Modales et dialogues
<div role="dialog" aria-modal="true" aria-labelledby="modal-title" aria-describedby="modal-description" class="modal" > <div class="modal-content"> <header class="modal-header"> <h2 id="modal-title">Confirmer la suppression</h2> <button type="button" class="btn-close" aria-label="Fermer" data-dismiss="modal" > <svg aria-hidden="true">...</svg> </button> </header> <div class="modal-body"> <p id="modal-description"> Êtes-vous sûr de vouloir supprimer cet élément ? </p> </div> <footer class="modal-footer"> <button type="button" class="btn btn-secondary" data-dismiss="modal"> Annuler </button> <button type="button" class="btn btn-danger"> Supprimer </button> </footer> </div> </div>
Exigences :
role="dialog"etaria-modal="true"aria-labelledbyetaria-describedby- Focus piégé dans la modale (tabulation circulaire)
- Fermeture avec Échap
- Retour du focus à l'élément déclencheur à la fermeture
- Fond (backdrop) bloque les interactions avec le contenu sous-jacent
Notifications et alertes
<!-- Message de succès --> <div role="status" aria-live="polite" class="alert alert-success"> <svg aria-hidden="true" class="icon">...</svg> <span>Document enregistré avec succès.</span> <button type="button" class="btn-close" aria-label="Fermer l'alerte"> <svg aria-hidden="true">...</svg> </button> </div> <!-- Message d'erreur --> <div role="alert" aria-live="assertive" class="alert alert-danger"> <svg aria-hidden="true" class="icon">...</svg> <span>Une erreur s'est produite lors de l'enregistrement.</span> </div>
Exigences :
role="alert"ourole="status"selon la criticitéaria-live="polite"ouaria-live="assertive"- Message textuel clair, pas uniquement visuel
- Bouton de fermeture accessible
Patterns d'interaction accessibles
Navigation au clavier
| Touche | Action |
|---|---|
| Tab | Naviguer vers l'élément suivant |
| Shift+Tab | Naviguer vers l'élément précédent |
| Enter | Activer un lien ou un bouton |
| Espace | Activer un bouton, cocher une case |
| Échap | Fermer une modale, un menu déroulant |
| Flèches | Naviguer dans les menus, tabs, listes |
Skip links
<a href="#main-content" class="skip-link"> Aller au contenu principal </a> <!-- ... header, navigation ... --> <main id="main-content" tabindex="-1"> <!-- Contenu principal --> </main>
Le skip link permet aux utilisateurs de lecteurs d'écran de sauter la navigation répétitive.
Landmarks ARIA
<body> <header role="banner"> <!-- En-tête du site --> </header> <nav role="navigation" aria-label="Navigation principale"> <!-- Navigation --> </nav> <main role="main"> <!-- Contenu principal --> <aside role="complementary"> <!-- Contenu complémentaire --> </aside> </main> <footer role="contentinfo"> <!-- Pied de page --> </footer> </body>
Les landmarks permettent aux utilisateurs de lecteurs d'écran de naviguer rapidement entre les sections.
Animations et motion
Respect de prefers-reduced-motion
/* Animation par défaut */ .card { transition: transform 200ms ease-out, box-shadow 200ms ease-out; } .card:hover { transform: translateY(-4px); box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1); } /* Désactiver les animations pour les utilisateurs sensibles */ @media (prefers-reduced-motion: reduce) { .card { transition: none; } .card:hover { transform: none; /* Garder uniquement le changement visuel statique */ box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1); } }
Règles d'animation accessibles
- Durée : 150-250ms (cf.
specs/design.md) - Pas de clignotement > 3 fois par seconde
- Possibilité de mettre en pause les animations longues
- Pas d'animation automatique > 5 secondes sans contrĂ´le utilisateur
Mode sombre accessible
/* Mode clair (par défaut) */ :root { --text-primary: var(--slate-12); --bg-primary: var(--slate-1); --border: var(--slate-6); } /* Mode sombre */ @media (prefers-color-scheme: dark) { :root { --text-primary: var(--slate-1); --bg-primary: var(--slate-12); --border: var(--slate-7); } } /* Vérifier que les contrastes restent conformes en mode sombre */
Radix Colors fournit automatiquement des palettes adaptées au mode sombre avec des contrastes conformes.
Responsive et zoom
Support du zoom texte jusqu'Ă 200%
- Pas de taille de police fixe en pixels (utiliser
rem,em) - Pas de
overflow: hiddenqui coupe le contenu zoomé - Layout fluide qui s'adapte au zoom
/* ✅ BON */ body { font-size: 1rem; /* 16px par défaut */ line-height: 1.6; } h1 { font-size: 2rem; /* 32px par défaut */ } /* ❌ MAUVAIS */ body { font-size: 16px; /* Ne s'adapte pas aux préférences utilisateur */ }
Responsive
- Mobile first
- Breakpoints cohérents
- Ordre de tabulation logique sur toutes les tailles d'écran
- Cibles tactiles ≥ 44×44px sur mobile
Checklist d'accessibilité UI
- Contrastes conformes WCAG AA (4.5:1 pour texte, 3:1 pour composants)
- Navigation clavier complète
- Focus visible sur tous les éléments interactifs (2px outline)
- Cibles tactiles ≥ 44×44px
- Labels visibles et associés pour tous les champs
- Messages d'erreur clairs et annoncés (
aria-live) - HTML sémantique (structure de document correcte)
- Hiérarchie des titres respectée (h1 → h2 → h3)
- Landmarks ARIA pour navigation rapide
- Skip links implémentés
- Alternatives textuelles pour tous les éléments non-textuels
- Icônes décoratives masquées (
aria-hidden="true") - Informations jamais transmises uniquement par la couleur
- Modales accessibles (focus trap, Échap pour fermer)
- Tableaux avec
<caption>et<th scope> - Animations respectent
prefers-reduced-motion - Pas de clignotement > 3 fois/sec
- Support du zoom jusqu'Ă 200% sans perte de contenu
- Mode sombre accessible (contrastes conformes)
- Tests avec lecteurs d'écran (NVDA, JAWS, VoiceOver)
- Tests avec navigation clavier seule
Outils de validation
Tests automatisés
- axe DevTools : Extension navigateur
- Lighthouse : Audit dans Chrome DevTools
- WAVE : Évaluation visuelle
Tests manuels
- Navigation au clavier (Tab, Shift+Tab, Enter, Échap, Flèches)
- Lecteurs d'écran (NVDA, JAWS, VoiceOver)
- Zoom du navigateur jusqu'Ă 200%
- Vérification des contrastes avec Colour Contrast Analyser
Tests utilisateurs
- Tests avec des personnes en situation de handicap
- Tests avec différentes technologies d'assistance
- Tests sur différents appareils et navigateurs
Ressources
Patterns ARIA du W3C
Guides Radix UI
- Radix UI : Composants accessibles unstyled
- Radix Colors : Palettes avec contrastes conformes