Skip to content

Talentech/flatpickr-a11y

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Accessible Flatpickr

License: MIT

Accessible Flatpickr provides WCAG-aligned behaviour for any Flatpickr instance. It enhances keyboard navigation, focus management, announcements, and ARIA primitives without changing the way you configure Flatpickr.

Features

  • Automatic enhancement: importing the bundle wraps window.flatpickr so every picker you create gains the accessibility layer by default.
  • Manual API: call initAccessibleFlatpickr when you want explicit control in module environments.
  • Keyboard support: Arrow keys, Home/End, Page Up/Down (with Shift for year jumps), Enter/Space, Escape, and Tab are all handled with guarded focus states.
  • Screen reader announcements: a live region reports open/close events, date selections, and focus changes.
  • Robust focus handling: tabbable calendars, Shift+Tab/Tab traversal across inputs, and outside-click dismissal.
  • Localization: five built-in languages (EN, PL, DA, SV, NO) with runtime language detection and custom locale registration.
  • Type-safe: shipped with TypeScript definitions for every public API.

Getting Started

Install with npm

npm install accessible-flatpickr flatpickr

Then import the enhancer before you create any pickers:

import 'accessible-flatpickr';
import flatpickr from 'flatpickr';

flatpickr('#my-date', { dateFormat: 'Y-m-d' });

Load from a CDN

<link
  rel="stylesheet"
  href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css"
>
<script src="https://cdn.jsdelivr.net/npm/flatpickr"></script>
<script src="https://cdn.jsdelivr.net/npm/accessible-flatpickr/dist/accessible-flatpickr.umd.js"></script>

<input type="text" id="my-date" placeholder="Select date">
<script>
  flatpickr('#my-date', { dateFormat: 'Y-m-d' });
  // window.flatpickr is already enhanced at this point.
</script>

Manual initialization

If you prefer to opt-in per instance, use the exported helper instead of the auto wrapper:

import { initAccessibleFlatpickr, createDefaultOptions } from 'accessible-flatpickr';

const fp = initAccessibleFlatpickr('#my-date', {
  dateFormat: 'Y-m-d',
  ...createDefaultOptions({
    onOpen(selectedDates, dateStr, instance) {
      console.log('Calendar opened', instance);
    }
  })
});

createDefaultOptions merges your callbacks with the accessibility hooks so you can plug the handlers into an existing Flatpickr configuration.

Localization

Built-in languages

Code Language
EN English
PL Polish
DA Danish
SV Swedish
NO Norwegian

The library chooses a language in this order:

  1. window.accessibleFlatpickrLanguage (or globalThis.accessibleFlatpickrLanguage in non-browser environments)
  2. The locale configured on the Flatpickr instance (flatpickr('#date', { locale: 'pl' }))
  3. English fallback
<script>
  window.accessibleFlatpickrLanguage = 'PL';
  flatpickr('#date', { dateFormat: 'Y-m-d' });
</script>

Custom locales

Register additional translations at runtime:

import { registerLocale } from 'accessible-flatpickr/dist/locales';

registerLocale('FR', {
  calendarOpened: 'Calendrier ouvert',
  calendarClosed: 'Calendrier fermé',
  dateSelected: 'Date sélectionnée :',
  today: " (aujourd'hui)",
  previousMonth: ' (mois précédent)',
  nextMonth: ' (mois suivant)',
  selectDate: 'Sélectionner une date',
  instructions: "Utilisez les flèches pour naviguer. Entrée sélectionne, Échap ferme. Page Haut/Bas change le mois.",
  dateSelection: 'Sélection de date',
  monthlyCalendar: 'Calendrier mensuel',
  previousMonthButton: 'Mois précédent',
  nextMonthButton: 'Mois suivant'
});

Use getAvailableLocaleCodes() from the same module to inspect the runtime registry.

Keyboard and Focus Behaviour

  • Arrow keys traverse days while keeping focus inside the calendar grid.
  • Home/End jump to the first or last visible day.
  • Page Up/Down move across months; hold Shift to move a full year.
  • Enter/Space activates the focused day button, announcing the chosen date.
  • Escape closes the calendar and returns focus to the originating input.
  • Tab / Shift+Tab close the current calendar and move focus to the next/previous tabbable control outside the picker.

Navigation buttons mirror their disabled state via aria-disabled and tabindex, so keyboard users never land on non-interactive controls.

Screen Reader Support

A visually hidden live region (#flatpickr-live-region) is injected during setup. It announces:

  • Calendar open/close lifecycle events
  • Date selections (localized month/day/year)
  • Focus changes triggered by keyboard navigation

Each day receives an aria-label with contextual hints such as “(today)” or “(next month)”. The calendar container itself is converted to a role="dialog" with aria-hidden toggled automatically.

Development

git clone <repository-url>
cd accessible-flatpickr
npm install
npm run dev

The Vite dev server opens http://localhost:3000/demo/index.html, which showcases:

  • A basic picker pair for Tab/Shift+Tab scenarios
  • A restricted-range calendar with disabled navigation buttons

Testing

  • npm run test – Vitest unit suite (mocked DOM).
  • npm run test:coverage – coverage report.
  • npm run test:ui – Vitest UI runner.
  • npm run test:e2e – Playwright end-to-end flow against the demo (ensure browsers are installed with npx playwright install).

Build

npm run build        # generates the UMD bundle in dist/
npm run build:types  # emits declaration files (run automatically by npm run build)
npm run preview      # serve the built demo

Project Structure

src/
├── core/               # Focus, click-outside, keyboard handling, language detection
├── enhancements/       # Input, calendar, navigation, top-level coordinator
├── locales/            # Built-in locale strings + registry
├── types/              # Public TypeScript definitions
├── utils/              # Live region + DOM helpers
└── index.ts            # Entry point and public API

Browser Support

  • Chrome 60+
  • Firefox 55+
  • Safari 12+
  • Edge 79+

Contributing

  1. Fork the repository.
  2. Branch from main.
  3. Implement your changes with tests.
  4. Run npm run test and npm run test:e2e.
  5. Open a pull request.

License

MIT – see the LICENSE file.

Acknowledgements

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors