Availability scheduler
BlockPick a day and a time slot from a host's availability.
pnpm dlx shadcn@latest add https://caliperui.site/r/availability-scheduler.jsonWhen to use #
Use it for
- Booking a meeting or demo.
Skip it when
- Time zones are not handled.
Installation #
terminal
pnpm dlx shadcn@latest add https://caliperui.site/r/availability-scheduler.json
Adds its 8 files to components/ui/, each with its own stylesheet, and installs their packages. No account needed. The first part also adds Caliper UI’s tokens; import them once as in Installation.
Usage #
This is the code behind the preview above.
example.tsx
import { useRef } from "react" import { AvailabilityScheduler } from "@/components/ui/availability-scheduler" const wait = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); const availability: Record<string, string[]> = {}; export function AvailabilitySchedulerDemo() { const tried = useRef(false); return ( <AvailabilityScheduler availability={availability} timeZone="Europe/London" duration={30} description="A 30 minute call with the team. Pick any open time." onConfirm={async ({ time }) => { await wait(900); if (time === "14:00" && !tried.current) { tried.current = true; return { error: "That time was just taken. Pick another." }; } }} /> ); }
API reference #
AvailabilityScheduler
component
PropTypeDefaultDescription
availability *Readonly<Record<string, readonly string[]>>—Open start times ("09:30") by ISO date. Days not listed are unavailable.
timeZone *string—A readable zone name, such as "Europe/London".
durationnumber30Minutes.
titlestring"Book a time"
descriptionstring—
onConfirm *(booking: { date: string; time: string; }) => SchedulerResult | Promise<SchedulerResult>—
classNamestring—
Accessibility #
It exposes status and group semantics, with aria-label and aria-hidden kept in step with state. Changes that matter are announced through a live region.
No custom key handling; Tab and the native activation keys do the work.
Motion #
Transitions use the shared duration and easing tokens. Under prefers-reduced-motion those tokens collapse to instant and travel distances go to zero, so state changes still happen without movement.