La sfida dell'ingresso di data sul Web

La selezione della data è una delle interazioni più comuni ma frustranti sul web. I raccoglitori di data del browser nativi variano selvaggiamente tra le piattaforme, e lo standard [ offre un controllo dello styling limitato e un comportamento inconsistente della tastiera.

Il raccoglitore di date accessibile non è solo in relazione alla conformità con le linee guida WCAG. Colpisce direttamente gli utenti reali: persone che navigano con le tastiere, coloro che si affidano ai lettori di schermo, persone con difetti motori che utilizzano dispositivi di commutazione, e chiunque beneficia di chiare immagini. Le tecniche qui coperte si applicano a qualsiasi framework JavaScript, ma gli esempi usano JavaScript vaniglia in modo da poterli adattare a React, Vue o qualsiasi altro ambiente.

Fondamenti di Accessibilità per i Pickers Data

Comprendere i Criteri di successo WCAG

L'accessibilità del pannello (SC 2.1.1) richiede che tutte le funzionalità siano valide attraverso un'interfaccia della tastiera. Focus visibile[ (SC 2.4.7) richiede un chiaro indicatore di messa a fuoco in modo che gli utenti sappiano quale data è selezionata. [FLTRIA:4]

HTML semantico come la spina dorsale

Inizia con elementi HTML semantici piuttosto che generici s. La griglia del calendario dovrebbe usare un [ elemento perché rappresenta semanticamente i dati tabulari. Ogni cella della data dovrebbe essere un elemento, che è intrinsecamente focalizzabile e attuabile tramite tastiera.

Architetto del componente del Picker Data

Elementi di interfaccia utente core

Un raccoglitore di date completo ha bisogno di questi componenti visivi e funzionali:

  • Un campo di input di testo che visualizza la data selezionata e attiva il popup del calendario
  • Un popup di calendario contenente un mese / anno intestazione, pulsanti di navigazione per i mesi di cambiamento, e una griglia di giorni
  • Data di oggi visivamente evidenziata per l'orientamento
  • La data selezionata è chiaramente contrassegnata con uno stile distinto
  • Un pulsante chiaro o Escape key per annullare il calendario senza selezionare

Gestione dello stato

Internamente, il raccoglitore di data deve tracciare diversi pezzi di stato: la data attualmente focalizzata (che può differire dalla data selezionata), il mese e l'anno visibile, il valore della data selezionata, e se il popup del calendario è aperto o chiuso.

Costruire la struttura HTML per l'accessibilità

Il campo di input

Il campo di input è il punto primario di interazione dell'utente, che deve comunicare il suo scopo e il suo rapporto con il popup del calendario utilizzando gli attributi ARIA:

Esempio di ingresso accessibile:[]

<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">

Il segnale di schema per le tecnologie assistive che questo input controlla un popup. L'attributo [ riflette dinamicamente se il calendario è visibile. Impostare l'ingresso come []] impedisce l'ingresso manuale del testo, permettendo la messa a fuoco della tastiera e gli eventi di clic.

Il dialogo del calendario

Il popup del calendario segue il dialogo[] modello da ARIA Authoring Practices. Dovrebbe essere reso come un fratello al campo di input nel DOM, tipicamente avvolto in un contenitore che gestisce il posizionamento:

<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">&lsaquo;</button>
 <h3 id="calendar-month-year" aria-live="polite">January 2025</h3>
 <button class="next-month" aria-label="Next month">&rsaquo;</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>

La sul tavolo fornisce una navigazione ottimizzata per i lettori di schermo all'interno di layout tabulari. Ogni cella della data dovrebbe essere un elemento [ esplicitamente applicato se si utilizza un elemento non semantico. La regione sul mese / anno intestazione assicura ai lettori di schermo di annunciare modifiche del mese senza interrompere l'utente.

Implementazione della navigazione della tastiera

Strategia di gestione del fuoco

Quando il calendario si apre, si sposta alla data attualmente selezionata, o alla data di oggi se non esiste una selezione. Questo segue il [] auto-focus finestra di dialogo[]]. Il calendario dovrebbe intrappolare l'attenzione all'interno di sé, impedendo all'utente di tabbing agli elementi dietro il popup.

Mapping eventi tastiera

I raccoglitori di data richiedono un'interfaccia di tastiera coerente. Il modello di griglia [] definisce le mappe di chiave standard per la navigazione dei contenuti tabulari:

  • I tasti freccia[[]]] si concentrano un giorno nella direzione corrispondente. Quando la messa a fuoco si sposta oltre il mese corrente, il calendario si sposta automaticamente al mese adiacente.
  • Home and End[]] spostare la concentrazione al primo o ultimo giorno del mese corrente.
  • Page Up and Page Down[] navigate al mese precedente o successivo, mantenendo il giorno del mese (clamato all'ultimo giorno del mese di destinazione, se necessario).
  • Inserisci o Spazio[[]] seleziona la data attualmente focalizzata e chiude il calendario.
  • Escape[]] chiude il calendario e ritorna concentrandosi sul campo di input.
  • Tab[]] si muove focalizzare all'interno dei componenti di dialogo (premi di navigazione mesi, griglia, oggi pulsante).

Gestione del tabindex roving

Usare il ]che migliora il tabindex[]] nella griglia della data. Un solo pulsante di data ha in qualsiasi momento, mentre tutti gli altri pulsanti della data hanno ]. Questo assicura che la pressione Tab entra una volta nella griglia e premendo Tab si sposta nuovamente al successivo elemento focalizzabile fuori della griglia.

Attributi ARIA per il supporto per lettore di schermo

Gestione dello stato ARIA dinamica

I lettori di schermo si affidano agli attributi ARIA per comunicare le modifiche dello stato. Aggiorna questi attributi in tempo reale, in quanto l'utente interagisce con il raccoglitore di data:

  • aria-espansione[[]] sull'ingresso: impostata a [] quando il calendario si apre, [ quando si chiude.
  • aria-hidden[[]] nella finestra di dialogo del calendario: rimuovere ([]) quando visibile, aggiungere [[]]] quando nascosto.
  • aria-seletto[]] sul pulsante della data selezionata: impostato a [ sulla data selezionata, [ su tutti gli altri.
  • aria-attivadescendant[] sull'ingresso: puntare all'ID della cella di data attualmente focalizzata.
  • aria-label[[]] su ogni tasto di data: includere la data completa, come "15 gennaio 2025" piuttosto che solo "15".

Annunciare modifiche di contesto

Quando l'utente naviga in un nuovo mese, annuncia il mese e l'anno utilizzando una regione dal vivo. Molte implementazioni aggiornano il [[]] nella finestra di dialogo o usano una regione visivamente nascosta []]]. Quando viene selezionata una data, annunciare "Gennaio 15, 2025 selezionato" per confermare l'azione.

Dettagli di implementazione JavaScript

Inizializzazione e configurazione

Creare una classe DatePicker o una funzione di fabbrica che accetta le opzioni di configurazione: l'elemento di ingresso, il formato di data, le date minime e massime e le funzioni di callback per la selezione della data.

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
}

Rendering del Calendario Grid

La funzione di rendering calcola il primo giorno del mese, il numero di giorni nel mese, e qualsiasi giorno di marcia dal precedente e dai prossimi mesi per riempire la griglia. Ogni pulsante riceve attributi dati per i componenti della data e un con la data leggibile dall'uomo:

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...
}

Delegazione Evento per Contenuto Dinamico

Invece di collegare gli ascoltatori di eventi ad ogni tasto di data singolarmente, utilizzare la delegazione di eventi sul contenitore di griglia. Ascoltare eventi sull'elemento [ e determinare quale data è stata cliccata utilizzando . Questo approccio gestisce le date generate dinamicamente senza riattaccare gli ascoltatori e riduce l'utilizzo della memoria.

Data di selezione

Quando un utente seleziona una data, il componente formatta la data in base al formato configurato, aggiorna il valore di input, memorizza la data selezionata internamente e chiama il callback. Dopo la selezione, il calendario chiude e si concentra all'ingresso.

Styling visivo per l'accessibilità

Contrasto e indipendenza del colore

Utilizzare una combinazione di colore di sfondo, colore di testo, bordo e decorazione di testo per comunicare stati selezionati, concentrati e disabilitati. Mantenere un rapporto di contrasto minimo di 3:1 per il contenuto non-text e 4.5:1 per il contenuto di testo per WCAG SC 1.4.3 e 1.4.11. Fornire un modo ad alto contrasto] che utilizza confini e sottolineature audacei invece di colori sottili.

Progettazione Indicatore di messa a fuoco

L'indicatore di messa a fuoco deve essere visibile contro tutti gli elementi circostanti. Utilizzare un [ o [ con sufficiente spessore e contrasto. Evitare di rimuovere il profilo del browser predefinito senza fornire una sostituzione. Un profilo solido da 3 pixel con un colore che contrasta sia lo sfondo predefinito e lo sfondo dello stato selezionato assicura visibilità.

Toccare la mira

Ogni tasto di data dovrebbe avere un obiettivo di contatto minimo di 44x44 pixel CSS, come raccomandato dal WCAG SC 2.5.8. Questo vale per dispositivi mobili, tablet e utenti con bassa destrezza che possono utilizzare il tocco o l'ingresso di stilo. Assicurare pulsanti di navigazione del mese e il pulsante di oggi soddisfano anche queste dimensioni minime. Se i vincoli di spazio richiedono obiettivi più piccoli, fornire l'imbottitura visiva o aumentare l'area cliccabile utilizzando -

Testare il tuo Picker data per l'accessibilità

Test manuale della tastiera

Prova il componente utilizzando solo una tastiera. Scheda in ingresso, apri il calendario con entrare o spazio, e naviga attraverso tutte le date utilizzando i tasti freccia. Verificare che Escape chiude il popup e restituisce la messa a fuoco all'ingresso. Confermare che l'indicatore di messa a fuoco è visibile in ogni momento e che l'ordine di messa a fuoco segue il layout visivo.

Test di lettore di schermo

Prova con almeno due lettori di schermo. Una combinazione di NVDA] (gratuito) con Firefox e JAWS (commerciale) con Chrome copre la maggior parte degli utenti di lettore di schermo. Verificare che il lettore di schermo annunci il ruolo di dialogo, il mese e l'anno, e la data in cui l'utente naviga.

Strumenti di test automatizzati

Utilizzare strumenti automatizzati come axe DevTools] o []Lighthouse per catturare problemi di accessibilità comuni. Questi strumenti possono identificare gli attributi mancanti ARIA, il contrasto di colore insufficiente e le etichette mancanti. Tuttavia, test automatizzati non possono rilevare tutti i problemi.

Considerazioni di integrazione nel mondo reale

Internazionalizzazione e localizzazione

Supporta più locali utilizzando l'API per formattare date e nomi dei mesi. Consentire la configurazione del primo giorno della settimana (Sunday vs. Monday) in base alla localizzazione.

Ottimizzazione di dispositivi mobili e touch

Considerare l'utilizzo di un modale a schermo intero per il calendario su piccoli schermi, con l'intera viewport dedicata all'interfaccia di selezione della data. Implementa i gesti di scorrimento per la navigazione del mese come un miglioramento progressivo.

Performance e dimensione del Bundle

Tenere il bundle JavaScript sotto 10KB minificata e incollata evitando inutili dipendenze e scrivendo codice efficiente. Utilizzare chiusure e funzioni di fabbrica per evitare overhead di ereditarietà di classe. Lazy-initialize il calendario DOM solo quando l'utente apre il picker, piuttosto che crearlo sul carico di pagina.

Custodie per bordi di gestione

Data di accesso disabili e ristretto

Implementare una funzione che controlla le date min/max, le restrizioni di giorno della settimana e le regole di esclusione personalizzate. Le date per disabili devono ricevere ed essere escluse dalla navigazione della tastiera.

Valori di infermeria e azioni chiare

Supporto per la cancellazione della data selezionata, fornendo un pulsante chiaro all'interno del footer del calendario o consentendo all'utente di fare clic sulla data selezionata. Quando non viene selezionata nessuna data, il segnaposto di ingresso deve comunicare il formato previsto. Il calendario dovrebbe aprire mostrando il mese corrente senza alcuna data evidenziata, ma con attenzione alla data di oggi per l'orientamento.

Browser e Compatibilità Quadro

Prestare particolare attenzione a Safari, che ha storicamente avuto supporto di indicatori di messa a fuoco inconsistente[]]. Utilizzare per fornire indicatori di messa a fuoco solo quando l'utente naviga attraverso la tastiera, evitando contorni persistenti su interazioni di clic.

Metterlo insieme

Un raccoglitore di data accessibile è costruito su una base di HTML semantico, un'attenta gestione ARIA e una robusta gestione degli eventi da tastiera. Il campo di input utilizza semantica combobox per comunicare il suo rapporto con il dialogo del calendario. La griglia delle date segue il modello tabindex roving per una navigazione efficiente della tastiera.

La vera misura del successo non è quanti attributi ARIA aggiungi, ma come si sente senza soluzione di continuità per gli utenti di tecnologia assistiva. Un raccoglitore di data ben costruito dovrebbe sentirsi altrettanto naturale per un utente di tastiera come fa a un utente del mouse.

L'accessibilità non è una funzione di manovra o un passo finale di lucidatura. È parte integrante del processo di progettazione e sviluppo. Quando si costruisce con l'accessibilità dall'inizio, si evita costosi refactors e offre una migliore esperienza per tutti gli utenti. Il raccoglitore di data è solo un componente, ma i principi che si applicano qui portano attraverso ogni elemento interattivo che si costruisce.