03-comment-je-travaille/accessibility/interface-utilisateur.md

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-visible pour 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, :disabled bien 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> avec aria-label descriptif
  • 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" et aria-modal="true"
  • aria-labelledby et aria-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" ou role="status" selon la criticitĂ©
  • aria-live="polite" ou aria-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: hidden qui 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

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

Références

Assistant documentaire

Posez une question sur la documentation. Les réponses citent leurs sources — un clic ouvre le document à gauche.

Loading…
Loading the web debug toolbar…
Attempt #