Skip to content
Halfpast
Back to Blog
Accessibility

A booking widget has to work with a keyboard

Calendars are one of the hardest things to make accessible and one of the easiest to get wrong. Notes from rebuilding ours twice.

Sander de Wit
Sander de Wit
2026-05-05 · 6 min read
A booking widget has to work with a keyboard

Our first booking calendar was a grid of divs with click handlers. It looked right, it worked with a mouse, and it was completely unusable with a keyboard or a screen reader. We have rebuilt it twice since.

Here is what we got wrong and what the current version does.

A day is a button, not a div

Obvious in hindsight. A clickable div is invisible to keyboard navigation and announces nothing. Every selectable day is now a real <button>, so it is focusable and operable for free, and an unavailable day is not a button at all — it is a plain element, so it never receives focus and never promises something it cannot do.

Selection state has to be announced

Styling the selected day with a background colour tells a sighted user which day is picked and tells a screen reader user nothing. The selected day now carries aria-pressed, so it is announced as pressed, and the styling hangs off that same attribute rather than a separate class. One source of truth, and they cannot disagree.

The grid is a table, because it is one

We tried a grid of buttons with ARIA roles. It was fragile. A month calendar is genuinely tabular data — days across, weeks down — so it is a <table> with weekday column headers. Screen readers already know how to navigate that, and we stopped fighting them.

The weekday headers show a single letter visually and the full day name to a screen reader, because “M T W T F S S” read aloud is not a weekday.

Colour is never the only signal

Slots come in three states. Available slots are outlined, nearly-full slots are tinted, and taken slots are dashed and disabled. If you removed all colour from the page you could still tell them apart by border style and by the fact that the third kind cannot be focused.

The thing still on our list

Keyboard arrow navigation within the calendar grid — pressing down to move a week rather than tabbing through 31 buttons. It works but tabbing through a month is tedious, and it is the most legitimate complaint we get. It is being worked on and it is honestly overdue.

Share this article

Pricing Try the booking flow