SlotPicker

SlotPicker accepts free slots as UTC ISO timestamps and groups them by day in the active IANA display zone. Choose it for public booking; use TimePicker when the application is collecting a local time rather than showing availability that already exists as instants.

Examples

Choose then confirm a slot

Slots stay UTC at the API boundary, but the calendar day and clock time shown here are computed in timezone. Selecting a time reveals a separate confirmation action, where the server should revalidate it.

SMTWTFS
New York
Monday, August 3

Translate the embedded zone picker

labels.timeZonePicker is forwarded directly to the embedded TimeZonePicker. Keep those nested labels with the SlotPicker translation so the change-time-zone path does not fall back to English.

SMTWTFS
New York
segunda-feira, 3 de agosto

When to use

Use SlotPicker when a person needs to browse finite, server-provided availability and confirm one slot.

Reach for something else when:

  • The person is entering an arbitrary local time — use TimePicker or TimeInput.
  • The application is defining availability — use WeeklyScheduleEditor before producing bookable instants.
  • The application is showing a broader calendar of events — use CalendarView.

Accessibility

  • Available times are a named role="listbox"; each time is a native button with role="option" and aria-selected. A selected slot is followed by the native confirmation button.
  • The changing availability area is aria-live="polite", including its loading skeleton and empty states. The embedded TimeZonePicker retains its searchable combobox keyboard behavior.
  • Calendar days with availability receive a visual marker and unavailable days are disabled. Visible and accessible date, time, hold and time-zone strings are configurable through locale and labels.

API and code

NameTypeRequiredDescription
slotsSlot[]—Free slots in UTC. The component groups them by active display-zone day.
datestring—Controlled visible local YYYY-MM-DD day.
defaultDatestring—Initial visible local YYYY-MM-DD day.
onDateChange(isoDate: string) => void—Called after the visible local day changes.
timezonestring—Controlled IANA display zone. Defaults to the browser-detected zone.
onTimezoneChange(zone: string) => void—Called after the active IANA display zone changes.
detectedZonestring—IANA zone shown as detected in the embedded TimeZonePicker.
onConfirm(slot: Slot) => void—Called after a user confirms a selected slot. Revalidate on the server.
confirmLabelstring—Confirmation button text. Default: Confirm.
holdExpiresAtstring—UTC ISO temporary-hold expiry. Its remaining duration is visible.
nextAvailableDatestring—Local YYYY-MM-DD target for an empty-day shortcut.
loadingboolean—Renders six slot pills while availability loads.
emptyMessagestring—Empty visible-day message.
fullMessagestring—Message when no slots exist in any day.
localestring—BCP 47 locale used for display times and dates. Default: en-US.
minDate | string—Inclusive local calendar lower limit.
maxDate | string—Inclusive local calendar upper limit.
childrenReactNode—Summary content rendered above the calendar.
labelsSlotPickerLabels—Translatable visible and accessible labels, merged over English defaults.

x-data="lyraSlotPicker({ … })"

OptionTypeRequiredDescription
slotsreadonly LyraSlot[]—Free slots in UTC. They are grouped by the active display-zone day.
datestring | null—Initial visible local `YYYY-MM-DD` day; modelable after initialization.
timezonestring—Initial IANA display zone; modelable after initialization.
detectedZonestring—IANA zone shown as detected in the embedded time-zone picker.
holdExpiresAtstring | null—UTC ISO temporary-hold expiry.
nextAvailableDatestring—Local `YYYY-MM-DD` target for an empty-day shortcut.
loadingboolean—Renders six slot pills while availability loads.
localestring—BCP 47 locale used for display times and dates. Default: `"en-US"`.
minstring—Inclusive local calendar lower limit.
maxstring—Inclusive local calendar upper limit.
labelsLyraSlotPickerLabels—Translatable labels merged over English defaults.
tzLabelsLyraTimeZonePickerLabels—Labels forwarded unchanged to the nested time-zone picker.

Without React, group UTC instants using the chosen display zone before rendering these classes:

html
<div class="lyra-slotpicker">
  <div class="lyra-slotpicker__side">August 3, 2026 · New York</div>
  <div class="lyra-slotpicker__main" aria-live="polite">
    <span class="lyra-slotpicker__daylabel">Monday, August 3</span>
    <div
      class="lyra-slotpicker__slots"
      role="listbox"
      aria-label="Available times for Monday, August 3"
    >
      <button class="lyra-slotpicker__slot" type="button" role="option" aria-selected="false">
        09:00 AM
      </button>
    </div>
  </div>
</div>

<lyra:slot-picker> Generated from lyra-ds/blade v0.10.0.

The behavior comes from lyraSlotPicker() — install @lyra-ds/alpine and see the HTML + Alpine tab.

PropDefaultRequiredExample values
slots[]——
datenull——
timezonenull—America/Sao_Paulo
detectedZonenull——
holdExpiresAtnull—2099-08-10T13:02:05Z
nextAvailableDatenull——
loadingfalse——
locale'en-US'——
minnull——
maxnull——
labels[]——
tzLabels[]——
blade
<lyra:slot-picker
    date="2026-03-17"
    timezone="America/Sao_Paulo"
    locale="en-US"
    :slots="[
        ['start' => '2026-03-17T13:00:00Z', 'end' => '2026-03-17T13:30:00Z'],
        ['start' => '2026-03-17T14:00:00Z', 'end' => '2026-03-17T14:30:00Z'],
        ['start' => '2026-03-17T15:30:00Z', 'end' => '2026-03-17T16:00:00Z'],
    ]"
/>