Almanac
Scheduling widget in three panes: a host card with duration chips, a keyboard-navigable month grid with availability dots and direction-aware month slides, and a day's time slots that cascade in, with a 12h/24h toggle and an IANA time-zone select (plain Intl, no date library). Picking a slot splits it into Confirm, then a details form slides in, an async onBook runs, and the button morphs into a confirmation card with a drawn check and an .ics Add to calendar button.
The preview is live. The source is Pro.
One purchase, lifetime access: every pro component's source, CLI install with your own registry token, and all future drops.
Installation
CLI
npx shadcn@latest add @crucible/almanacManual — install dependencies, then copy the source
npm install motionProps
| Prop | Type | Default | Description |
|---|---|---|---|
| host | AlmanacHost | a sample design-review host | Host and event details for the left pane. |
| durations | number[] | [15, 30, 60] | Duration chips in minutes. Changing the chip recomputes the slots. |
| defaultDuration | number | the middle entry of durations | Initially selected duration. |
| availability | AlmanacAvailability | Open slots for a day. Omit for a deterministic seeded generator (weekdays, working hours in hostTimeZone, a few busy blocks, nothing in the past, 60-day booking window) relative to today. | |
| today | Date | string | The day treated as "today" — a Date or "YYYY-MM-DD". Omit to use the real current day, computed after mount (a skeleton renders until then, so server and client markup match). | |
| timeZones | string[] | IANA zones offered in the time-zone select. The viewer's detected zone is added if missing. | |
| defaultTimeZone | string | the viewer's detected zone (after mount) | Initial time zone. |
| hostTimeZone | string | "America/New_York" | Zone the default availability generator schedules working hours in. |
| defaultHourCycle | "12h" | "24h" | "12h" | Initial clock format. |
| weekStartsOn | 0 | 1 | 0 | First day of the week in the month grid (0 = Sunday, 1 = Monday). |
| onBook | (booking: AlmanacBooking) => void | Promise<unknown> | Called with the booking when the details form is submitted. Return a Promise to hold the button in a pending state — resolve morphs into the confirmation card, reject shows the error's message inline. | |
| onAddToCalendar | (booking: AlmanacBooking) => void | downloads an .ics file for the booking | Override "Add to calendar". |
| onDurationChange | (minutes: number) => void | Fires when the duration chip changes. | |
| onTimeZoneChange | (tz: string) => void | Fires when the time zone changes. | |
| accentColor | string | "#a5b4fc" | Signature accent for selection, focus rings and the confirm button. |
| ref | React.Ref<AlmanacHandle> | Imperative handle (reset(), replay()). React 19 ref-as-prop. | |
| className | string | Extra classes for the <section> root. | |
Also accepts all props of Omit<React.ComponentPropsWithoutRef<"section">, "children" | "onChange" | "onDurationChange"> — they pass through to the underlying element. | |||
Honors prefers-reduced-motion with a designed static fallback, and passes className through.