Pourquoi l'Accessibilité ne concerne pas des "cases à cocher", mais des personnes
\nSoyons honnêtes : quand nous entendons "accessibilité" (ou a11y), beaucoup d'entre nous imaginent des listes interminables d'exigences, des vérifications ennuyeuses et la phrase "bon, c'est pour les personnes handicapées". Mais la vérité est que l'accessibilité concerne tout le monde. Avez-vous déjà essayé de commander une pizza en marchant, en tenant votre téléphone d'une seule main ? Ou étiez-vous dans le métro avec une mauvaise connexion Internet, où le site mettait une éternité à charger ? Ce sont là des problèmes d'accessibilité.
\nDans cet article, nous allons parler de la façon dont TypeScript peut devenir votre meilleur ami pour créer des applications web accessibles. Pas seulement "ajouter des balises", mais construire une architecture où l'inclusivité n'est pas une fonctionnalité, mais un fondement.
\n\nTypeScript comme bouclier contre les erreurs a11y
\nBeaucoup pensent que TypeScript ne concerne que les types de données et la protection contre les bugs. Mais en réalité, le typage strict peut aussi sauver en matière d'accessibilité. Analysons cela avec des exemples.
\n\nTypage des attributs ARIA
\nL'un des problèmes les plus courants est celui des valeurs incorrectes des attributs ARIA. Avez-vous déjà écrit role="button" sur un div ? Et ensuite oublié d'ajouter tabindex ? TypeScript peut détecter cela dès la compilation.
// Mauvais : aucune protection\nfunction createButton(label: string) {\n return `<div role="button">${label}</div>`;\n}\n\n// Bon : typage des ARIA\ntype AriaRole = 'button' | 'navigation' | 'alert' | 'dialog';\n\ninterface AriaAttributes {\n role: AriaRole;\n 'aria-label'?: string;\n 'aria-expanded'?: boolean;\n tabIndex?: number;\n}\n\nfunction createAccessibleButton(label: string, aria: AriaAttributes) {\n // Désormais, TypeScript vérifiera que le rôle est valide\n return {\n tag: 'div',\n attrs: aria,\n content: label\n };\n}\n\n// Erreur ! 'btn' ne fait pas partie du type AriaRole\n// createAccessibleButton('Cliquez-moi', { role: 'btn' });\nVous sentez la différence ? TypeScript ne vous laissera pas écrire accidentellement role="btutton" ou oublier un attribut obligatoire. C'est comme un assistant personnel qui murmure : "Hé, es-tu sûr que c'est accessible ?"
Vérification stricte des états de focus
\nUn autre point sensible est la gestion du focus. Surtout dans les SPA, où la page ne se recharge pas. TypeScript aide à créer des wrappers sécurisés.
\n// Définir quels éléments peuvent recevoir le focus\ntype FocusableElement = HTMLInputElement | HTMLButtonElement | HTMLAnchorElement | HTMLSelectElement | HTMLTextAreaElement;\n\nfunction safelySetFocus(element: FocusableElement | null): void {\n if (element && document.contains(element)) {\n element.focus();\n } else {\n console.warn('Élément introuvable dans le DOM ou ne peut pas recevoir le focus');\n }\n}\n\n// Utilisation\nconst modal = document.querySelector('.modal__close-btn');\nsafelySetFocus(modal as FocusableElement | null);\nRemarquez : nous n'appelons pas simplement .focus(), mais nous vérifions si l'élément existe et s'il peut être focalisé. Cela évite les erreurs qui pourraient laisser l'utilisateur d'un lecteur d'écran dans le vide.
Construire une architecture avec a11y à la base
\nPassons maintenant à des choses plus avancées. Comment faire pour que l'accessibilité soit intégrée dans l'architecture de votre projet, et non ajoutée "à la va-vite" avant la sortie ?
\n\nProps typés pour les composants
\nCréez une interface de base pour tous vos composants. C'est comme une constitution pour l'accessibilité.
\n// Interface de base pour tous les composants UI\ninterface AccessibleComponentProps {\n id?: string;\n className?: string;\n ariaLabel?: string;\n ariaDescribedby?: string;\n role?: string;\n tabIndex?: number;\n isDisabled?: boolean;\n onClick?: () => void;\n onKeyDown?: (e: React.KeyboardEvent) => void;\n}\n\n// Composant bouton spécifique\ninterface ButtonProps extends AccessibleComponentProps {\n variant