civil-and-structural-engineering
Construire un outil Javascript personnalisé avec support d'accessibilité
Table of Contents
Le défi de la date Introduire des commentaires sur le Web
La sélection de date est l'une des interactions les plus courantes mais frustrantes sur le web. Les sélectionneurs de date de navigateur natifs varient considérablement d'une plate-forme à l'autre, et la norme offre un contrôle de style limité et un comportement de clavier incohérent.
Un outil de sélection de date accessible ne se limite pas à la conformité aux directives WCAG. Il a des répercussions directes sur les utilisateurs réels : les personnes qui naviguent avec des claviers, celles qui comptent sur des lecteurs d'écran, les personnes ayant une déficience motrice qui utilisent des appareils de commutation, et toute personne qui bénéficie de signaux visuels clairs.
Les fondements de l'accessibilité pour les dattes
Comprendre les critères de réussite du WCAG
Plusieurs critères de réussite WCAG 2.1 s'appliquent directement aux sélectionneurs de date. L'accessibilité au clavier (SC 2.1.1) exige que toute fonctionnalité soit exploitable par une interface clavier. Focus visible (SC 2.4.7) exige un indicateur de focalisation clair afin que les utilisateurs sachent quelle date est sélectionnée. Nom, rôle, valeur (SC 4.1.2) garantit que les technologies d'assistance peuvent identifier le composant et son état actuel.
HTML sémantique comme l'os arrière
Commencer par des éléments HTML sémantiques plutôt que génériques s. La grille de calendrier devrait utiliser un élément parce qu'il représente sémantiquement des données tabulaires. Chaque cellule de date devrait être un élément , qui est intrinsèquement focalisable et activable par clavier. Éviter d'utiliser des éléments comme cibles interactives parce qu'ils ne sont pas pris en charge par le clavier natif et nécessitent un ARI supplémentaire pour communiquer l'interactivité.
Architecte du composant de la date de sélection
Éléments d'interface utilisateur de base
Un récupérateur de date complet a besoin de ces composants visuels et fonctionnels :
- Un champ d'entrée de texte qui affiche la date sélectionnée et déclenche la popup du calendrier
- Un popup de calendrier contenant un en-tête mois/année, des boutons de navigation pour les mois changeants, et une grille de jours
- La date d'aujourd'hui est visuellement mise en avant pour l'orientation
- La date sélectionnée est clairement marquée d'un style distinct
- Un bouton clair ou une touche Escape pour rejeter le calendrier sans sélectionner
Administration de l ' État
En interne, le récupérateur de date doit suivre plusieurs éléments d'état : la date actuellement focalisée (qui peut différer de la date sélectionnée), le mois et l'année visibles, la valeur de la date sélectionnée et si le popup du calendrier est ouvert ou fermé. Maintenez ces variables comme variables JavaScript et mettez à jour les attributs DOM et ARIA en réponse aux changements d'état.
Construire la structure HTML pour l'accessibilité
Le champ d'entrée
Le champ d'entrée est le point d'interaction principal de l'utilisateur. Il doit communiquer son but et sa relation avec le popup du calendrier en utilisant les attributs ARIA:
Exemple d'entrée accessible:
<label for="date-picker-input">Departure date</label>
<input type="text"
id="date-picker-input"
role="combobox"
aria-haspopup="dialog"
aria-expanded="false"
aria-controls="datepicker-calendar"
aria-autocomplete="none"
readonly
placeholder="MM/DD/YYYY">
Le modèle indique aux technologies d'assistance que cette entrée contrôle un popup. L'attribut reflète dynamiquement si le calendrier est visible. La configuration de l'entrée comme empêche l'entrée manuelle de texte tout en permettant la mise au point du clavier et les événements de clic.
La boîte de dialogue de calendrier
Le calendrier suit le modèle dialog[ de l'ARIA Authoring Practices. Il devrait être rendu comme un frère au champ d'entrée dans le DOM, généralement enveloppé dans un conteneur qui gère le positionnement:
<div id="datepicker-calendar"
role="dialog"
aria-modal="true"
aria-label="Choose a date"
hidden>
<div class="calendar-header">
<button class="prev-month" aria-label="Previous month">‹</button>
<h3 id="calendar-month-year" aria-live="polite">January 2025</h3>
<button class="next-month" aria-label="Next month">›</button>
</div>
<table class="calendar-grid" role="grid" aria-labelledby="calendar-month-year">
<thead>
<tr>
<th scope="col"><abbr title="Sunday">Sun</abbr></th>
<th scope="col"><abbr title="Monday">Mon</abbr></th>
<th scope="col"><abbr title="Tuesday">Tue</abbr></th>
<th scope="col"><abbr title="Wednesday">Wed</abbr></th>
<th scope="col"><abbr title="Thursday">Thu</abbr></th>
<th scope="col"><abbr title="Friday">Fri</abbr></th>
<th scope="col"><abbr title="Saturday">Sat</abbr></th>
</tr>
</thead>
<tbody>
<!-- Date rows rendered dynamically -->
</tbody>
</table>
<div class="calendar-footer">
<button class="today-button">Today</button>
</div>
</div>
Chaque cellule de date devrait être un élément avec le explicitement appliqué si l'on utilise un élément non sémantique. La région sur le titre mois/année assure aux lecteurs d'écrans d'annoncer des changements de mois sans interrompre l'utilisateur.
Mise en œuvre de la navigation par clavier
Stratégie de gestion axée sur les résultats
Lorsque le calendrier s'ouvre, focus se déplace vers la date actuellement sélectionnée, ou à la date d'aujourd'hui si aucune sélection n'existe. Ceci suit le modèle de boîte de dialogue autofocus. Le calendrier devrait piéger focus en lui-même pendant l'ouverture, empêchant l'utilisateur de tabasser vers des éléments derrière la popup. Implémenter un piège focus qui cycle entre le premier et le dernier élément focalisable dans la boîte de dialogue.
Cartographie des événements du clavier
Les sélectionneurs de dates exigent une interface de clavier cohérente. Le modèle ARIA définit les cartes de clés standard pour la navigation du contenu tabulaire :
- Les touches de démarrage déplacent la focalisation d'un jour dans la direction correspondante. Lorsque la focalisation se déplace au-delà du mois en cours, le calendrier se déplace automatiquement vers le mois adjacent.
- La maison et la fin déplacent le focus vers le premier ou le dernier jour du mois en cours.
- Page haut et page bas naviguent jusqu'au mois précédent ou suivant tout en préservant le jour du mois (clamé au dernier jour du mois cible si nécessaire).
- Entrer ou espace[ sélectionne la date actuellement focalisée et ferme le calendrier.
- Escape ferme le calendrier et retourne le focus au champ d'entrée.
- Tab déplace la mise au point dans les composants de dialogue (boutons de navigation de mois, grille, bouton d'aujourd'hui).
Gestion de l'index des onglets itinérants
Utilisez le modèle roving tabindex dans la grille de dates. Un seul bouton de date a à tout moment, tandis que tous les autres boutons de date ont . Cela garantit que la touche Tab entre une fois dans la grille et appuie de nouveau sur Tab se déplace vers le prochain élément focalisé en dehors de la grille. Lorsque les touches fléchées déplacent focus, mettez à jour les valeurs en conséquence et appelez sur la cellule nouvellement active.
Attributs ARIA pour le support de lecteur d'écran
Gestion dynamique de l'État de l'ARIA
Les lecteurs d'écran se fient aux attributs ARIA pour communiquer les changements d'état. Mettez à jour ces attributs en temps réel lorsque l'utilisateur interagit avec le sélectionneur de date:
- aria-expanded[ sur l'entrée: définie à lorsque le calendrier s'ouvre, quand il se ferme.
- aria-hidden sur la boîte de dialogue du calendrier : supprimer () quand visible, ajouter ([) quand caché.
- aria-sélectionné sur le bouton de date sélectionné: défini à sur la date choisie, sur tous les autres. Notez que les boutons supportent nativement un état pressé, mais est l'attribut correct pour les rôles de cellules de grille.
- sur l'entrée: pointez sur l'ID de la cellule de date actuellement ciblée.
- sur chaque bouton de date : inclure la date complète, comme « 15 janvier 2025 » plutôt que « 15 ».
Annonce des changements de contexte
Lorsque l'utilisateur navigue vers un nouveau mois, annoncez le mois et l'année en utilisant une région en direct. De nombreuses implémentations mettent à jour la sur la boîte de dialogue ou utilisent une région cachée visuellement . Lorsqu'une date est sélectionnée, annoncez «15 janvier 2025 sélectionnée» pour confirmer l'action.
Détails de l'implémentation JavaScript
Initialisation et configuration
Créez une fonction de classe DatePicker ou d'usine qui accepte les options de configuration : l'élément d'entrée, le format de date, les dates minimales et maximales et les fonctions de rappel pour la sélection de la date. Initialiser en mettant en place les auditeurs de l'événement sur l'entrée et en rendant le mois initial du calendrier :
class AccessibleDatePicker {
constructor(input, options = {}) {
this.input = input;
this.options = Object.assign({
format: 'MM/DD/YYYY',
minDate: null,
maxDate: null,
onDateSelect: () => {}
}, options);
this.selectedDate = null;
this.focusedDate = null;
this.currentMonth = new Date().getMonth();
this.currentYear = new Date().getFullYear();
this.isOpen = false;
this.calendar = this.buildCalendarElement();
this.setupEventListeners();
}
// ... methods
}
Rendu de la grille de calendrier
La fonction rendu calcule le premier jour du mois, le nombre de jours du mois et les jours suivants pour remplir la grille. Chaque bouton de date reçoit des attributs de données pour les composantes de date et une avec la date lisible par l'homme:
renderMonth() {
const firstDay = new Date(this.currentYear, this.currentMonth, 1).getDay();
const daysInMonth = new Date(this.currentYear, this.currentMonth + 1, 0).getDate();
const daysInPrevMonth = new Date(this.currentYear, this.currentMonth, 0).getDate();
let cells = [];
// Add trailing days from previous month
for (let i = firstDay - 1; i >= 0; i--) {
cells.push(this.createDateButton(daysInPrevMonth - i, this.currentMonth - 1, this.currentYear, true));
}
// Add days of current month
for (let day = 1; day <= daysInMonth; day++) {
cells.push(this.createDateButton(day, this.currentMonth, this.currentYear));
}
// Add leading days of next month
const remaining = 42 - cells.length; // 6 rows × 7 columns
for (let day = 1; day <= remaining; day++) {
cells.push(this.createDateButton(day, this.currentMonth + 1, this.currentYear, true));
}
// Render into table body...
}
Délégation d'événement pour le contenu dynamique
Au lieu d'attacher les auditeurs d'événements à chaque bouton de date individuellement, utilisez la délégation d'événements sur le conteneur de grille. Écoutez les événements sur l'élément et déterminez quelle date a été cliqué en utilisant . Cette approche gère les dates générées dynamiquement sans réaccrocher les auditeurs et réduit l'utilisation de la mémoire.
Déroulement de la sélection de la date
Lorsqu'un utilisateur choisit une date, le composant formate la date selon le format configuré, met à jour la valeur d'entrée, stocke la date sélectionnée en interne et appelle le callback . Après la sélection, le calendrier se ferme et le focus retourne à l'entrée. Mettre à jour l'attribut sur la cellule précédemment sélectionnée à et sur la cellule nouvellement sélectionnée à . Déclencher un événement personnalisé sur l'élément d'entrée afin que d'autres scripts écoutant des modifications puissent réagir.
Style visuel pour l'accessibilité
Indépendance de contraste et de couleur
La couleur ne devrait jamais être le seul indicateur de l'état. Utilisez une combinaison de couleur de fond, de couleur de texte, de bordure et de décoration de texte pour communiquer les états sélectionnés, focalisés et désactivés. Maintenir un rapport de contraste minimal de 3:1 pour le contenu non textuel et de 4.5:1 pour le contenu textuel par WCAG SC 1.4.3 et 1.4.11. Fournir un mode de contraste élevé qui utilise des bordures audacieuses et souligne au lieu de changements subtils de couleur.
Conception des indicateurs de référence
L'indicateur de focalisation doit être visible contre tous les éléments environnants. Utilisez un ou avec une épaisseur et un contraste suffisants. Évitez de supprimer le contour du navigateur par défaut sans fournir de remplacement. Un contour solide de 3 pixels avec une couleur qui contraste avec le fond par défaut et l'arrière-plan de l'état sélectionné assure la visibilité.
Taille de la cible tactile
Chaque bouton de date devrait avoir une cible de touche minimale de 44x44 pixels CSS, comme le recommande le WCAG SC 2.5.8. Ceci s'applique aux appareils mobiles, aux tablettes et aux utilisateurs à faible dextérité qui peuvent utiliser le toucher ou le stylet. Assurez-vous que les boutons de navigation du mois et le bouton d'aujourd'hui répondent également à ces dimensions minimales.
Testez votre date de sélection pour l'accessibilité
Essai manuel du clavier
Testez le composant en utilisant seulement un clavier. Onglet dans l'entrée, ouvrez le calendrier avec Entrée ou Espace, et naviguez à travers toutes les dates en utilisant des touches fléchées. Vérifiez que Escape ferme le popup et retourne le focus à l'entrée. Confirmez que l'indicateur de focus est visible en tout temps et que l'ordre de focus suit la mise en page visuelle. Testez avec les touches Page Up, Page Down, Home et Fin pour s'assurer qu'ils effectuent la navigation prévue mois et jour. Documentez tout comportement inattendu et corrigez-le avant de considérer le composant complet.
Test du lecteur d'écran
Testez avec au moins deux lecteurs d'écran. Une combinaison de NVDA (gratuit) avec Firefox et JAWS[ (commercial) avec Chrome couvre la majorité des utilisateurs de lecteurs d'écran. Vérifiez que le lecteur d'écran annonce le rôle de dialogue, le mois et l'année, et la date que l'utilisateur navigue. Confirmez que état est annoncé et que la date sélectionnée est communiquée lorsque la boîte de dialogue s'ouvre. Testez avec un lecteur d'écran sur un appareil mobile en utilisant TalkBack (Android) ou VoiceOver (iOS) pour assurer le fonctionnement de la navigation tactile.
Outils de test automatisés
Utilisez des outils automatisés comme axe DevTools[ ou Lighthouse[ pour saisir des problèmes d'accessibilité communs. Ces outils peuvent identifier les attributs d'ARIA manquants, le contraste de couleur insuffisant et les étiquettes manquantes. Cependant, les tests automatisés ne peuvent pas détecter tous les problèmes.
Considérations relatives à l'intégration dans le monde réel
Internationalisation et localisation
Les sélectionneurs de dates servent un public mondial. Supportent plusieurs localités en utilisant l'API pour formater les dates et les noms de mois. Permet la configuration du premier jour de la semaine (dimanche vs lundi) en fonction de la localité. En-têtes de jours de semaine de rendu utilisant des noms abrégés qui respectent la localité. Fournir des traductions pour les étiquettes ARIA telles que «mois précédent» et «Choisir une date».
Optimisation des touches et des mobiles
Sur les appareils mobiles, positionnez la boîte de dialogue calendrier pour éviter de se chevaucher avec le clavier virtuel. Considérez l'utilisation d'un mode plein écran pour le calendrier sur les petits écrans, avec l'ensemble du port de vue dédié à l'interface de sélection de la date. Implémentez des gestes de balayage pour la navigation mensuelle comme une amélioration progressive. Testez sur les appareils mobiles réels avec l'entrée de lecteur tactile et d'écran pour confirmer que les cibles tactiles sont suffisamment grandes et que les actions de gestes ont des retombées accessibles.
Performance et taille de la trousse
Un sélecteur de date personnalisé ne devrait pas gonfler votre application. Gardez le paquet JavaScript sous 10Ko minifié et gzipped en évitant les dépendances inutiles et en écrivant un code efficace. Utilisez les fermetures et les fonctions d'usine pour éviter les frais de classe. Initialiser le calendrier DOM seulement lorsque l'utilisateur ouvre le sélecteur, plutôt que de le créer sur la charge de page.
Traitement des cas de bord
Dates d'invalidité et de restriction
Mettre en œuvre une fonction qui vérifie les dates min/max, les restrictions du jour de la semaine et les règles d'exclusion personnalisées. Les dates désactivées devraient recevoir et être exclues de la navigation du clavier. Visualement, les dates désactivées devraient utiliser une opacité réduite et éviter les effets de survol. Lorsqu'un utilisateur passe la grille, sautez les dates désactivées entièrement.
Valeurs nulles et actions claires
Si aucune date n'est sélectionnée, le détenteur de place d'entrée doit communiquer le format prévu. Le calendrier doit s'ouvrir en affichant le mois en cours sans date en surbrillance, mais en mettant l'accent sur la date d'aujourd'hui pour l'orientation. Persistez le dernier mois sélectionné afin que si l'utilisateur rouvre le calendrier, il retourne au mois qu'il a visionné précédemment.
Compatibilité navigateur et cadre
Testez le détecteur de date sur Chrome, Firefox, Safari et Edge. Faites une attention particulière à Safari, qui a toujours eu un support de l'indicateur de focalisation non cohérent. Utilisez pour fournir des indicateurs de focalisation uniquement lorsque l'utilisateur navigue via le clavier, en évitant les contours persistants sur les interactions de clic.
Tout mettre en place
Un outil de sélection de dates accessible est construit sur une base de HTML sémantique, une gestion attentive de l'ARIA et une gestion robuste des événements clavier. Le champ d'entrée utilise la sémantique combobox pour communiquer sa relation avec la boîte de dialogue calendrier. La grille de dates suit le modèle d'index des onglets pour une navigation efficace du clavier.
La vraie mesure du succès n'est pas combien d'attributs ARIA vous ajoutez, mais comment l'expérience se fait pour les utilisateurs de technologie d'assistance. Un correcteur de date bien construit devrait se sentir tout aussi naturel pour un utilisateur de clavier que pour un utilisateur de souris. En suivant les modèles décrits ici et en testant soigneusement avec de vraies technologies d'assistance, vous créez un composant qui sert tout le monde.
L'accessibilité n'est pas une fonction à basculer ou une étape finale de polissage. Elle fait partie intégrante du processus de conception et de développement. Lorsque vous construisez avec l'accessibilité dès le début, vous évitez les refacteurs coûteux et offrez une meilleure expérience pour tous les utilisateurs. Le sélectionneur de dates n'est qu'un élément, mais les principes que vous appliquez ici portent sur chaque élément interactif que vous construisez.