Tutorial: Building an Accessible Date Picker Component from Scratch
accessibilitytutorialcomponents

Tutorial: Building an Accessible Date Picker Component from Scratch

AAnya Patel
2025-11-29
10 min read
Advertisement

Step-by-step walkthrough to build an accessible, themeable date picker component with keyboard navigation, ARIA attributes, and sensible defaults.

Tutorial: Building an Accessible Date Picker Component from Scratch

Calendar widgets are deceptively complex. Building an accessible, usable date picker requires careful handling of focus management, keyboard navigation, screen reader semantics, and internationalization. This tutorial walks through building a production-ready date picker that is themeable with design tokens and works well across desktop and mobile.

Goals: keyboard-first accessibility, proper ARIA usage, token-based theming, and a small API surface. We'll use a minimal framework-agnostic approach: a small glue layer for rendering and a focus on semantics rather than framework magic. The core concepts translate to React, Vue or vanilla usage.

Core accessibility considerations

At the heart of an accessible picker are these constraints:

  • Focus should move only to interactive elements; opening the calendar should move focus to the currently selected date.
  • Keyboard navigation must cover arrow keys for adjacent days, PageUp/PageDown for month jumps, and Home/End for week extremes.
  • Use proper ARIA roles: role="grid" for the calendar container, role="row" for weeks and role="gridcell" for days.
  • Announce visible changes: when month changes, provide an accessible label update for screen readers.

Rendering strategy

Keep rendering separated from logic. The date generator produces a matrix of dates for the current month, and the renderer maps that matrix to DOM nodes. For token-based theming, read CSS variables for colors, spacing and focus outlines. Avoid inline styles for theming; prefer exposing class hooks where tokens map easily to CSS variables.

Keyboard interactions

Attach a keydown listener to the calendar root and handle these keys:

  • ArrowLeft / ArrowRight: move one day.
  • ArrowUp / ArrowDown: move one week (minus or plus 7 days).
  • PageUp / PageDown: move to previous / next month.
  • Home / End: move to start / end of the current week.
  • Enter / Space: select focused date and emit select event.

When moving focus across month boundaries, update the displayed month accordingly and announce the new month label using an aria-live region for polite updates.

ARIA semantics example

Use role attributes carefully. A simplified structure:

<div role="application">
  <div role="grid" aria-label="Calendar - May 2026">
    <div role="row">
      <button role="gridcell" aria-selected="false">1</button>
    </div>
  </div>
</div>

Ensure the currently focused gridcell receives tabindex="0" and others receive tabindex="-1". This allows screen readers to keep track and prevents tabbing out of the grid while navigating with arrow keys.

Internationalization

Support for different week starts (Sunday vs Monday) and localized month and weekday names is essential. Provide a locale prop that maps to Intl.DateTimeFormat for labels, and allow an optional function for custom parsing when your app has special date formats.

Testing

Automated tests should cover keyboard sequences and screen reader announcements. Use tools like axe-core for accessibility checks, and write integration tests that simulate keyboard navigation, verifying that focus and aria-selected states update as expected.

Packaging and API

Keep the component API minimal: selectedDate, onSelect(date), locale, tokens (for theme overrides), and an optional portal option for rendering the calendar in a top-level container to avoid clipping and z-index issues.

Wrap-up

Accessible components require deliberate design decisions. By focusing on keyboard interactions, ARIA semantics, and clear API boundaries, you can build a date picker that integrates with design systems and provides a great experience for all users. The full source and runnable example are available on our GitHub repo and include a detailed test suite and demo pages for common edge cases.

Advertisement

Related Topics

#accessibility#tutorial#components
A

Anya Patel

Accessibility Engineer

Senior editor and content strategist. Writing about technology, design, and the future of digital media. Follow along for deep dives into the industry's moving parts.

Advertisement