Deck
Browse the catalog

Build / Molecules

TimeSlotPicker

  • molecule

Time-of-day picker for a booking flow's availability step.

Slots are grouped into morning, afternoon, and evening rather than listed as one run, because "sometime in the afternoon" is how people actually decide — an ungrouped column of a dozen times makes them read every one. Empty periods are omitted, so a morning-only day shows a single group.

Renders as a radio group so arrow keys move between times.

import { TimeSlotPicker } from '@meetcard/deck'

Example

<TimeSlotPicker value={time} onChange={setTime} timeZone="America/Denver" slots={[{ time: '09:00' }, { time: '09:30', taken: true }]} />

Stories

Every preview below is the real component, rendered in this page from the same story Storybook runs. The width control resizes each preview's container; CSS media queries still follow the browser window, so breakpoint behaviour is worth checking in Storybook.

Default
Source
const Default = args => {
    const [value, setValue] = useState(args.value)

    return (
        <TimeSlotPicker
            timeZone="America/Denver"
            slots={[
              { time: '09:00' },
              { time: '09:30' },
              { time: '10:00', taken: true },
              { time: '10:30' },
              { time: '11:00' },
              { time: '13:00' },
              { time: '14:00' },
              { time: '14:30', taken: true },
              { time: '15:30' },
              { time: '17:00' },
              { time: '17:30' },
            ]}
            value={value}
            onChange={setValue} />
    );
};

A slot chosen, ready to confirm.

Selected
Source
const Selected = args => {
    const [value, setValue] = useState(args.value)

    return (
        <TimeSlotPicker
            timeZone="America/Denver"
            slots={[
              { time: '09:00' },
              { time: '09:30' },
              { time: '10:00', taken: true },
              { time: '10:30' },
              { time: '11:00' },
              { time: '13:00' },
              { time: '14:00' },
              { time: '14:30', taken: true },
              { time: '15:30' },
              { time: '17:00' },
              { time: '17:30' },
            ]}
            value={value}
            onChange={setValue} />
    );
};

Periods with no slots are omitted, so a morning-only day shows one group.

Morning Only
Source
const MorningOnly = args => {
    const [value, setValue] = useState(args.value)

    return (
        <TimeSlotPicker
            timeZone="America/Denver"
            slots={[{ time: '08:00' }, { time: '08:30' }, { time: '09:00' }]}
            value={value}
            onChange={setValue} />
    );
};

Props

PropTypeDefaultDescription
slotsrequiredTimeSlot[]——
classNamestring——
labelstring'Pick a time'—
localestring——
onChange(time: string) => void——
timeZonestring—IANA zone the times are expressed in, shown alongside the label.
valuestring—HH:mm of the selected slot.

Open in Storybookfor controls, the a11y panel and the interaction runner.