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
- Gestion des stocks distribués : l'architecture événementielle de VinoTrack
- Collaboration en temps réel à grande échelle : l'approche des microservices d'EchoStream
- Visualisation de données haute performance : moteur WebGL de NebulaGraph
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