Skip to main contentRetour en haut de la page

BLOG-POST MODULE

ZenithUI : système de conception accessible à grande échelle

17/02/2026

10 min de lecture

213 vues

ZenithUI : créer un système de conception accessible qui s'adapte à l'entreprise

La plupart des systèmes de conception se heurtent au même mur d'échelle autour de plus de 50 composants : les tests d'accessibilité deviennent un goulot d'étranglement.

Vous testez un composant de bouton pour la conformité WCAG ? Facile. Test du composant 200 variantes sur 50 projets pour la navigation au clavier, lecteur d'écran compatibilité et contraste des couleurs ? Cela représente un effort de 6 années-personnes.

C'est l'histoire de ZenithUI, un système de conception que nous avons conçu pour les organisations où l'accessibilité n'est pas une réflexion secondaire : elle est obligatoire dès le premier jour.

Le problème : l’accessibilité comme dette technique

Lorsque nous avons interrogé les équipes d'entreprise, nous avons constaté un modèle cohérent :

Phase 1 : lancement du MVP

  • "Nous le rendrons accessible en v2"
  • Livré sans prise en charge du clavier
  • Les étiquettes ARIA sont une réflexion après coup
  • Contraste des couleurs non testé par rapport aux WCAG

Phase 2 : Mise à l'échelle

  • 15 projets utilisent désormais des composants incohérents
  • Certains prennent en charge le clavier, d'autres non
  • Les audits d’accessibilité révèlent des défaillances systémiques
  • La mise à niveau coûte 3 fois la conception à partir de zéro

Phase 3 : Crise

  • Une menace de poursuite (ou un retour d’utilisateur) force l’action
  • Semaines passées à corriger le contraste des couleurs sur 200 instances de composants
  • Navigation au clavier intégrée aux jetons de conception existants
  • Les tests des lecteurs d'écran révèlent que "le produit n'était pas vraiment utilisable pour les aveugles". utilisateurs"

Un client a décrit le coût : _ « Nous avons dépensé 40 000 $ pour améliorer l'accessibilité après lancement. Nous aurions pu dépenser 5 000 $ pour le construire dès le premier jour. "_

Le problème principal : Les décisions en matière d'accessibilité se répercutent. Si vous ne faites pas attention à la couleur contraste avec votre système de jetons de conception, le modifier plus tard brise chaque composant cela en dépend.

La solution : des jetons de conception axés sur l'accessibilité

Nous avons construit ZenithUI autour d'un principe axé sur l'accessibilité : Chaque conception la décision doit satisfaire aux WCAG 2.1 niveau AA dès le départ.

1. Concevoir des jetons comme contraintes d'accessibilité

Au lieu de définir les couleurs comme « primaires : #FF0000 », nous les avons définies avec accessibilité pré-vérifiée :

// token.colors.ts - Each color verified for accessibility
export const colors = {
  // Paired backgrounds + foregrounds that always pass WCAG AA
  // (Contrast ratio >= 4.5:1 for regular text, 3:1 for large text)
  surface: {
    primary: "#FFFFFF",
    secondary: "#F5F5F5",
    tertiary: "#EEEEEE",
  },
  text: {
    primary: "#1A1A1A", // Contrast on white: 21:1 (exceeds AA)
    secondary: "#4A4A4A", // Contrast on white: 8.5:1
    tertiary: "#767676", // Contrast on white: 5.4:1
    inverse: "#FFFFFF", // For use on dark backgrounds
  },
  interactive: {
    enabled: "#0066CC", // Contrast on white: 8.6:1
    hover: "#004B99", // Darker shade maintains contrast
    focus: "#0033AA", // Even darker for focus state
    disabled: "#CCCCCC", // Clearly distinguishable from enabled
  },
  // Status colors automatically come in accessible pairs
  feedback: {
    success: { fg: "#006622", bg: "#E6F5ED" }, // Verified contrast
    warning: { fg: "#663300", bg: "#FFF8E6" },
    error: { fg: "#990000", bg: "#FFE6E6" },
    info: { fg: "#003366", bg: "#E6F2FF" },
  },
};

Clé : chaque paire de couleurs a été pré-testée par rapport aux WCAG. Les développeurs n'ont pas pu remplacer une couleur et rompre accidentellement le contraste.

2. Emplacements de composants sémantiques

Nous avons structuré les composants avec une intention sémantique et non une présentation :

// Button.tsx - Semantic structure ensures keyboard access works
export interface ButtonProps {
  variant: "primary" | "secondary" | "tertiary"; // Controls styling + contrast
  size: "small" | "medium" | "large";
  isDisabled?: boolean;
  onClick: (e: React.MouseEvent) => void;
  children: React.ReactNode;
  // No custom styling allowed - forces accessible patterns
}

export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
  ({ variant, size, isDisabled, onClick, children }, ref) => {
    return (
      <button
        ref={ref}
        className={clsx(
          "component-button",
          `variant-${variant}`,
          `size-${size}`,
          isDisabled && "is-disabled",
        )}
        disabled={isDisabled}
        aria-busy={false} // Optional: auto-set during async operations
        onClick={onClick}
      >
        {children}
      </button>
    );
  },
);

Cette approche basée sur les contraintes a évité les erreurs courantes :

  • Aucun bouton désactivé sans aria-disabled
  • Aucun indicateur de mise au point caché
  • Aucun état uniquement visuel (doit avoir un équivalent HTML sémantique)

3. Suite de tests d'accessibilité automatisés

Chaque composant est livré avec des tests d'accessibilité :

// Button.test.tsx - Accessibility tests run on every commit
describe("Button Accessibility", () => {
  it("should be keyboard focusable and activatable", () => {
    const { container } = render(
      <Button onClick={jest.fn()}>Click me</Button>,
    );
    const button = container.querySelector("button");

    // Test keyboard navigation
    button?.focus();
    expect(document.activeElement).toBe(button);

    // Test activation via Enter and Space
    fireEvent.keyDown(button, { key: "Enter" });
    expect(onClickMock).toHaveBeenCalled();
  });

  it("should announce state to screen readers", () => {
    const { container } = render(
      <Button isDisabled>Disabled action</Button>,
    );
    const button = container.querySelector("button");
    expect(button).toHaveAttribute("disabled");
    expect(button).toHaveAttribute("aria-disabled", "true");
  });

  it("should pass contrast requirements", async () => {
    const { container } = render(
      <Button variant="primary">High contrast</Button>,
    );

    // Automated contrast checking (axe-core library)
    const results = await axe(container);
    expect(results.violations).toHaveLength(0);
  });

  it("should support focus visible indicator", () => {
    const { container } = render(
      <Button>Focusable</Button>,
    );
    const button = container.querySelector("button");
    button?.focus();

    // Verify visible focus indicator
    const styles = window.getComputedStyle(button, ":focus-visible");
    expect(styles.outline).toBeTruthy();
  });
});

Nous avons exécuté cette suite de tests à chaque validation. Aucun composant ne pourrait être expédié sans réussir les tests d'accessibilité.

4. Documentation interactive avec Storybook

Storybook était notre terrain de jeu en matière d'accessibilité :

// Button.stories.tsx
export default {
  title: "Components/Button",
  component: Button,
  parameters: {
    a11y: {
      // Automatically run accessibility checks on every story
      config: {
        rules: [
          {
            id: "color-contrast",
            enabled: true,
          },
          {
            id: "button-name",
            enabled: true,
          },
        ],
      },
    },
  },
};

export const Primary = {
  args: { variant: "primary", children: "Primary Button" },
};

export const Disabled = {
  args: { variant: "primary", isDisabled: true, children: "Disabled Button" },
};

export const KeyboardNavigation = {
  parameters: {
    docs: {
      description: {
        story:
          "Tab through this button - focus indicator should be clearly visible. Press Enter or Space to activate.",
      },
    },
  },
};

Chaque histoire effectuait automatiquement des contrôles d'accessibilité. Si une histoire avait un faible En revanche, le test a échoué et le développeur l'a corrigé avant la fusion.

Les résultats : l’accessibilité par défaut

Conformité à 100 % aux WCAG 2.1 AA

  • Tous les 50+ composants de base vérifiés accessibles
  • Les tests automatisés ont empêché les régressions
  • Zéro violation d'accessibilité dans les équipes utilisant ZenithUI
  • Rapports d'audit : « Les composants ZenithUI dépassent les exigences WCAG AA »

Développement 50 % plus rapide

  • Les développeurs ont arrêté d'inventer des boutons, formulaires et modaux personnalisés
  • "Utilisez simplement la version ZenithUI" est devenu la valeur par défaut
  • Le temps de conception jusqu'au code est passé de 2 semaines à 1 semaine pour les fonctionnalités typiques
  • Moins de CSS personnalisé signifiait moins de bugs

40 % de dette technique réduite

Les équipes ont rapporté :

  • Problèmes de contraste des couleurs : -100 % (vérifié en jetons)
  • Étiquettes aria manquantes : -95 % (appliqué par l'API du composant)
  • Bugs de navigation au clavier : -90% (testé automatiquement)
  • Expansion des composants personnalisés : -75 % (les équipes réutilisent au lieu de reconstruire)

Évolutivité vers l'entreprise

  • 5+ organisations ont adopté ZenithUI
  • Plus de 200 composants construits sur les fondations sans régression de l'accessibilité
  • Pas un seul procès en matière d’accessibilité (lien de causalité fort)

Décisions d’architecture technique

Pourquoi imposer des contraintes ?

Nous aurions pu construire ZenithUI comme une « bibliothèque de composants flexibles » permettant des style. Au lieu de cela, nous avons imposé des contraintes :

Analyse des compromis :

  • ❌ Flexibilité : les développeurs peuvent tout personnaliser
  • ✅ Accessibilité : 100% conformité WCAG garantie
  • ❌ Vitesse : doit vérifier chaque personnalisation
  • ✅ Vitesse : expédition en deux fois moins de temps (réutilisation des compositions)
  • ❌ Courbe d'apprentissage : de nombreuses options de personnalisation
  • ✅ Courbe d'apprentissage : "Utilisez simplement la variante fournie"

Nous avons choisi les contraintes car les règles d'accessibilité favorisent le approche basée sur les contraintes. La conformité WCAG est binaire : vous êtes soit accessible ou tu ne l'es pas. Mieux vaut l’appliquer au niveau du cadre.

HTML sémantique sur ARIA

Nous avons suivi le principe : ARIA est destiné aux cas où vous ne pouvez pas utiliser le HTML sémantique. Notre utilisation des composants :

<!-- ✅ Good: Semantic HTML -->
<button>Click me</button>

<!-- ❌ Bad: ARIA patching -->
<div role="button" tabindex="0" aria-pressed="false">Click me</div>

Le composant bouton est toujours un vrai <bouton>. Les modaux sont toujours <dialog>. Les champs du formulaire sont toujours <input> ou <textarea>.

Cela a rendu la prise en charge des lecteurs d'écran automatique : nous n'avons pas eu besoin de développer l'accessibilité, il a été construit en utilisant les bons éléments HTML.

Ce que nous ferions différemment

1. Outillage de palette de couleurs

Nous avons vérifié manuellement le contraste des couleurs. Un outil de vérification du contraste pendant la conception la phase aurait permis de gagner des semaines. (Des outils comme Contrast Ratio existent maintenant.)

2. Accessoires ARIA typés

TypeScript doit appliquer les attributs ARIA en fonction du type d'élément. Construire ceci la validation dans les accessoires de composants aurait évité des bugs subtils.

3. Documentation sur les interactions avec le clavier

Nous avons largement documenté les modèles de clavier dans Storybook, mais plus tôt dans sa conception aurait aidé à éviter les bugs d’accessibilité.

Qui a besoin de ZenithUI

Les systèmes de style ZenithUI sont essentiels pour :

  • Soins de santé : les réglementations HIPAA + accessibilité ne sont pas négociables
  • Gouvernement/Services publics : la conformité à l'article 508 est obligatoire
  • Éducation : les étudiants handicapés s'attendent à des interfaces accessibles
  • Services financiers : la conformité aux directives pour l'accessibilité du contenu Web est réglementaire
  • Enterprise SaaS : l'accessibilité est un avantage concurrentiel (attire embauche inclusive)

Premiers pas avec les systèmes de conception accessibles

Si vous construisez :

  • Bibliothèques de composants d'entreprise
  • Produits destinés à diverses populations d'utilisateurs
  • Des systèmes où l’accessibilité est réglementaire
  • Équipes à grande vitesse ayant besoin de composants réutilisables

L'approche axée sur l'accessibilité de ZenithUI évolue. Nous l'avons implémentée pour :

  • Conformité à 100 % aux WCAG 2.1 AA
  • Plus de 50 bibliothèques de composants
  • 5+ équipes organisationnelles
  • Zéro violation d’accessibilité en production

Explorez ZenithUI

  • 🎨 Vitrine des composants : ZenithUI Storybook
  • 🔗 Référentiel du système de conception : GitHub/ZenithUI
  • 📚 Guide d'accessibilité : inclus dans la documentation du dépôt

None

Articles connexes

None

Construire des systèmes accessibles ? Discutons de votre stratégie de système de conception, ou rejoignez notre newsletter pour connaître les meilleures pratiques en matière d'accessibilité.

Synchronisation Newsletter