Accessible Date Pickers and Delivery Calendars at Checkout

Delivery date pickers fail keyboard and screen reader users in predictable ways: unlabeled grid buttons, dates announced without weekdays, and no text alternative. How to test and fix them.

A delivery calendar looks simple. It is a grid of numbers, a couple of arrows, and a confirm button. For a keyboard user it can be the hardest control in the whole checkout, because every choice depends on focus order, visible focus, and whether a screen reader announces a date as a date or as a bare number with no weekday attached.

WCAG 2.2 is clear about the pieces involved. Names and roles come under 4.1.2, status messages under 4.1.3, and keyboard operability under 2.1.1. A calendar that only works with a pointer fails all three in one widget, and it fails at the exact moment a customer is trying to pay.

What the grid actually announces

Tab into a typical calendar and listen. Many implementations expose each day as a button with a number as its only name, so the announcement is button, 14, button, 15, with no month, no weekday, and no indication of which days are unavailable. The shopper has to hold the whole month in memory while arrowing around, which is not a minor inconvenience. It is the task itself being withheld.

Unavailable dates are often handled worse. Greyed text that is still focusable tells nobody anything, and grey on white frequently fails the 4.5 to 1 contrast ratio WCAG 1.4.3 requires for normal text. If a date cannot be chosen, say so in the accessible name, or remove it from the tab order and explain the pattern in text above the calendar.

The text field nobody offers

The cheapest fix is rarely built: a plain text field next to the calendar that accepts a typed date in a stated format, with an example. Typed input removes the grid problem entirely for many users, works with voice control, and gives the store a value it can validate and read back for confirmation.

Validation matters as much as entry. If the typed date is a Sunday and the store does not deliver on Sundays, the error should name that fact and offer the nearest available days in words. An error that just turns the field red and says invalid date fails 3.3.1, and it sends the shopper back to the grid they were avoiding.

A test you can run this week

Unplug the mouse. Open checkout, tab to the date picker, and try to choose the second Tuesday from now using only the keyboard. Note where focus disappears, whether the month changes are announced, and whether the chosen date is confirmed anywhere in text after selection.

Then repeat it with a screen reader at normal speed. If you cannot state, from the announcements alone, which date you picked and what day of the week it falls on, neither can your customers. Log that as a defect with the criterion numbers attached, not as a polish item.

Related reading

If this topic is useful, these earlier guides go deeper on connected questions: Accessible Promo Code Entry at Checkout, Accessible Order Tracking Pages and Delivery Updates, and Accessible Loyalty Points Dashboards Shoppers Can Actually Read.

Frequently asked questions

Does WCAG require a specific calendar design?

No. WCAG sets outcomes, not components. Any design passes if it is keyboard operable, each date has a proper name and role, unavailable dates are identifiable, and the selection is confirmed in a way assistive technology can announce.

Is a typed date field enough on its own?

It can be, provided the format is stated with an example, errors explain what was wrong and what to try instead, and the confirmed date is read back in full. A typed field with silent rejection is no better than a broken grid.

How should unavailable dates be handled?

Make them identifiable without relying on colour alone. Add text such as unavailable to the accessible name, keep contrast readable, and explain delivery patterns in plain text above the calendar so nobody has to probe every date.

What should happen when the month changes?

The new month and year should be announced as a status message, and focus should stay where the user put it. Calendars that throw focus back to the first day on every arrow click force the whole task to restart.