FrontendPro

85Build a date picker with keyboard navigation and disabled dates

mediumAbout 45 minutesCodingreactdatesaccessibilitykeyboard

Problem

Build <DatePicker value="2026-10-14" onChange={fn} min max isDateDisabled />. Dates are ISO strings ("YYYY-MM-DD").

Render one month:

  • an <h2> with the month and year, for example October 2026, and buttons labelled Previous month and Next month;
  • a <table role="grid"> with weekday headers (Su to Sa) and one row per week; days of other months are empty cells;
  • each day is a <button data-date="2026-10-01"> with aria-selected="true" on the selected date and aria-disabled="true" on disabled dates (before min, after max, or where isDateDisabled(iso) is true).

Requirements

  • Clicking an enabled day calls onChange(iso). Disabled days do nothing (but stay focusable for keyboard users).
  • Only one day is in the Tab order (roving tabIndex): the focused day, which starts at the selected date.
  • Keyboard on a day: ArrowLeft/ArrowRight move one day, ArrowUp/ArrowDown one week, Home/End to the start or end of the week, PageUp/PageDown one month (keeping the day, clamped to the month's length), Enter selects. Moving into another month shows that month and keeps focus on the new day.
  • No timezone bugs: 2026-03-29 must stay 2026-03-29 in every timezone.

Try it yourself

Write your solution, run it, then submit to check it against the tests.

App.jsxReact + DOM

Step-by-step

Parse "YYYY-MM-DD" into Date.UTC(y, m - 1, d) and read it back with getUTCFullYear, getUTCMonth and getUTCDate. Local-time Dates shift by an hour across daylight-saving changes, which turns some dates into the previous day. toISOString().slice(0, 10) formats a UTC date back to an ISO string.

Unlock the full solution

What's inside

  • Step-by-step
  • Approach
  • Solution
  • Complexity
  • Edge cases
  • Follow-up questions
  • Tests

Includes 2 code listings, 5 edge cases, 4 follow-up questions.

One-time payment by UPI, card or net banking. Launch price.

All 150 answersOne payment, yours forever