DEV Community

A11ySolutions
A11ySolutions

Posted on

The Date Picker That Looks Fine and Blocks Every Keyboard User

A date picker in a form. Visually, it works. Click it, a calendar opens, pick a date, done.

Tab to it instead of clicking, and it doesn't exist. No focus outline, no response to Enter, nothing. This is one of the most repeated patterns in our audit data, and it's almost always the same root cause.

What's actually happening

html
<div class="datepicker-trigger" onclick="openDatepicker()">
  Select date
</div>

<input type="hidden" name="date-field" id="date-field">
Enter fullscreen mode Exit fullscreen mode

The visible trigger is a <div> with a click handler and nothing else. No tabindex, no role, no keyboard events. Tab skips right over it. The value itself lives in a hidden input, which is invisible to the accessibility tree by design.

A mouse user never notices anything is wrong. A keyboard user hits this step and simply cannot continue. Not a degraded experience, a full stop. This fails WCAG 2.1.1 (Keyboard) at critical severity, and it shows up constantly in date pickers, custom dropdowns, and color pickers, wherever a hidden input holds the real value and a styled div handles the visuals.

The fix

Make the trigger a real interactive element, with keyboard support and a name that reflects its current state:

html
<button
  id="date-trigger"
  aria-haspopup="dialog"
  aria-label="Date, no date selected"
  aria-expanded="false">
  Select date
</button>

<input
  type="text"
  id="date-field"
  name="date-field"
  aria-label="Selected date"
  placeholder="DD/MM/YYYY"
  autocomplete="bday">
Enter fullscreen mode Exit fullscreen mode
javascript
dateTrigger.addEventListener('keydown', (e) => {
  if (e.key === 'Enter' || e.key === ' ') {
    e.preventDefault();
    openDatepicker();
  }
});
Enter fullscreen mode Exit fullscreen mode

Why this also breaks AI agents

An agent navigating a page by its accessibility tree hits the same wall a keyboard user does. A <div> with no role and no keyboard handling isn't a control it can act on, it's just text. If the real value sits in a hidden input, the agent has no way to read or set it either. Same structural gap, same failure, whether the thing trying to complete the form is a person or an automated agent.

The fix costs a few lines. The div-with-onclick pattern costs every keyboard and agent-driven interaction that touches it.

Top comments (0)