SLOT PICKER: Single-select radiogroup of booking time-slot chips, grouped by day column
COMPOSES: .empty-state (no slots available) · slot_picker_controller.js
Used for open-day / interview slot booking (Events vertical). Click a slot to book it —
only one slot can be selected across the whole picker. Arrow keys move focus between
available slots without selecting (Enter/Space or click selects); taken slots are real
disabled buttons, skipped automatically by both Tab and the arrow keys.
St Mary's Academy — Open Day. Three Saturday mornings, six 30-minute
slots each. Taken slots are dimmed, unclickable, and carry a visible "Taken" label
(never color alone) plus an aria-label that says so explicitly.
Label in Name (WCAG 2.5.3): each chip's aria-label opens with
the chip's own visible text, then adds the day —
aria-label="09:00, Saturday 12 September", not
"9:00 AM, Saturday 12 September". The date context is what makes a bare
"09:00" unambiguous across three day columns, but it has to come after the visible
string or a voice-control user saying "click 09:00" activates nothing. Taken chips render
two lines, so their name leads with both —
aria-label="09:30 Taken, Saturday 12 September".
We'll email your confirmation as soon as you pick a time.
<div data-controller="slot-picker"><div class="slot-picker"><div class="slot-picker-grid" role="radiogroup">…<button class="slot-picker-slot" role="radio" aria-checked="false">09:00</button>…</div><input type="hidden" data-slot-picker-target="value"></div></div>
Editing an existing booking: the server renders the previously-booked
slot with class="selected", aria-checked="true", and
tabindex="0". The controller reads this on connect, sets the hidden value,
and leaves the roving tab stop on the already-selected slot.
Fully booked date: when a day has zero available slots, the grid is
replaced with .empty-state — no interactive picker is rendered at all,
so there is nothing to focus that can't be used.
All Open Day visit slots for Saturday 3 October are booked. Try another date, or join the waiting list and we'll email you if a slot frees up.
<div class="slot-picker"><div class="card"><div class="empty-state">…</div></div></div>