Time Slot Picker
Preview: Default
Grid of bookable time slots grouped by part of day (radio group: arrow keys move, booked slots disabled).
Import
import { TimeSlotPicker } from '@marbleui/ui'Props
<TimeSlotPicker>
| Prop | Type | Default | Description |
|---|---|---|---|
| groups *required | { title: string; slots: TimeSlot[]; }[] | — | |
| onChange *required | (id: string) => void | — | |
| className | string | — | |
| label | string | 'Time' | |
| value | string | — |
Accessibility
Keyboard interaction, focus management and ARIA semantics come from the underlying primitives: React Aria Radio · React Aria RadioGroup. Follow the primitive's docs for the full keyboard map.
Usage notes
TimeSlotPicker shows bookable times as a grid grouped by part of day, with booked slots crossed out and disabled. It is a radio group, so one slot is chosen at a time; for free time entry use TimeField.
const [slot, setSlot] = useState<string>()
<TimeSlotPicker
label="Meeting time, Tuesday 21 October"
groups={[
{ title: 'Morning', slots: [{ id: '09:00', label: '9:00 AM' }, { id: '09:30', label: '9:30 AM', disabled: true }] },
{ title: 'Afternoon', slots: [{ id: '13:00', label: '1:00 PM' }] },
]}
value={slot}
onChange={setSlot}
/>
- Controlled:
onChangereceives the slotid; store it and pass it back asvalue. Withoutvaluenothing shows as selected, and there is nodefaultValue. label(default “Time”) is only the accessible name and isn’t rendered, so include the date in it. Each group’stitleis both the visible heading and the group’s name.- Arrow keys move through all slots, across groups, skipping disabled ones, and select as they go. Book from a separate confirm button, not from
onChange.
Example source · show· hide
import { useState } from 'react'
import { TimeSlotPicker } from './time-slot-picker'
const mk = (hs: string[], booked: string[]) => hs.map((h) => ({ id: h, label: h, disabled: booked.includes(h) }))
const groups = [{ title: 'Morning', slots: mk(['09:00', '09:30', '10:00', '10:30', '11:00', '11:30'], ['09:30', '11:00']) }, { title: 'Afternoon', slots: mk(['13:00', '13:30', '14:00', '15:00', '15:30', '16:00'], ['14:00']) }]
function Demo() {
const [v, setV] = useState<string>()
return <div className="flex w-96 flex-col gap-3"><TimeSlotPicker label="Meeting time, Tuesday Oct 21" groups={groups} value={v} onChange={setV} /><span aria-live="polite" className="text-sm text-fg-muted">{v ? `Booked ${v}, 30 minutes` : 'Pick a slot'}</span></div>
}
export const styles = { Default: Demo }Source: packages/ui/src/time-slot-picker/time-slot-picker.tsx
Catalog
- Category
- date-time
- Priority
- Extra
- Primitive
- composed
- React Aria
- GridList