Schedule
Read-only schedule shell for day, week, month, and list views.
Examples
Section titled “Examples”August 2026
Sun
Mon
Tue
Wed
Thu
Fri
Sat
function ScheduleStory({ categories: storyCategories = categories, events: storyEvents = events, height, highlightDate = defaultHighlightDate, plugins, timezoneID = localTimezoneID, view, viewDate: initialViewDate = defaultViewDate,}: { categories?: ReadonlyArray<ScheduleCategory>; events?: ScheduleEventSource; height?: ScheduleHeight; highlightDate?: Instant; plugins?: SchedulePlugin[]; timezoneID?: string; view: ScheduleView; viewDate?: Instant;}) { const [viewDate, setViewDate] = useState<Instant>(() => initialViewDate); const paginationPlugin = useSchedulePaginationPlugin({ onViewDateChange: setViewDate, }); return ( <Schedule categories={storyCategories} events={storyEvents} height={height} highlightDate={highlightDate} plugins={plugins ?? [paginationPlugin]} timezoneID={timezoneID} view={view} viewDate={viewDate} /> );}
<ScheduleStory view={createScheduleMonthlyView()} />August 2026
Sun23
Mon24
Tue25
Wed26
Thu27
Fri28
Sat29
function ScheduleStory({ categories: storyCategories = categories, events: storyEvents = events, height, highlightDate = defaultHighlightDate, plugins, timezoneID = localTimezoneID, view, viewDate: initialViewDate = defaultViewDate,}: { categories?: ReadonlyArray<ScheduleCategory>; events?: ScheduleEventSource; height?: ScheduleHeight; highlightDate?: Instant; plugins?: SchedulePlugin[]; timezoneID?: string; view: ScheduleView; viewDate?: Instant;}) { const [viewDate, setViewDate] = useState<Instant>(() => initialViewDate); const paginationPlugin = useSchedulePaginationPlugin({ onViewDateChange: setViewDate, }); return ( <Schedule categories={storyCategories} events={storyEvents} height={height} highlightDate={highlightDate} plugins={plugins ?? [paginationPlugin]} timezoneID={timezoneID} view={view} viewDate={viewDate} /> );}
<ScheduleStory events={weekEvents} view={createScheduleWeeklyView({maxHour: 18, minHour: 8})}/>Narrow Week
Section titled “Narrow Week”August 2026
Sun23
Mon24
Tue25
Wed26
Thu27
Fri28
Sat29
function ScheduleStory({ categories: storyCategories = categories, events: storyEvents = events, height, highlightDate = defaultHighlightDate, plugins, timezoneID = localTimezoneID, view, viewDate: initialViewDate = defaultViewDate,}: { categories?: ReadonlyArray<ScheduleCategory>; events?: ScheduleEventSource; height?: ScheduleHeight; highlightDate?: Instant; plugins?: SchedulePlugin[]; timezoneID?: string; view: ScheduleView; viewDate?: Instant;}) { const [viewDate, setViewDate] = useState<Instant>(() => initialViewDate); const paginationPlugin = useSchedulePaginationPlugin({ onViewDateChange: setViewDate, }); return ( <Schedule categories={storyCategories} events={storyEvents} height={height} highlightDate={highlightDate} plugins={plugins ?? [paginationPlugin]} timezoneID={timezoneID} view={view} viewDate={viewDate} /> );}
<div className={narrowWeekStoryContainer}> <ScheduleStory events={weekEvents} view={createScheduleWeeklyView({ dayMinWidth: 128, maxHour: 18, minHour: 8, })} /></div>Availability
Section titled “Availability”August 2026
Sun23
Mon24
Tue25
Wed26
Thu27
Fri28
Sat29
function ScheduleStory({ categories: storyCategories = categories, events: storyEvents = events, height, highlightDate = defaultHighlightDate, plugins, timezoneID = localTimezoneID, view, viewDate: initialViewDate = defaultViewDate,}: { categories?: ReadonlyArray<ScheduleCategory>; events?: ScheduleEventSource; height?: ScheduleHeight; highlightDate?: Instant; plugins?: SchedulePlugin[]; timezoneID?: string; view: ScheduleView; viewDate?: Instant;}) { const [viewDate, setViewDate] = useState<Instant>(() => initialViewDate); const paginationPlugin = useSchedulePaginationPlugin({ onViewDateChange: setViewDate, }); return ( <Schedule categories={storyCategories} events={storyEvents} height={height} highlightDate={highlightDate} plugins={plugins ?? [paginationPlugin]} timezoneID={timezoneID} view={view} viewDate={viewDate} /> );}
() => { const availabilityPlugin = useScheduleAvailabilityPlugin({ getUnavailableRanges: getStoryUnavailableRanges, }); return ( <ScheduleStory events={weekEvents} plugins={[availabilityPlugin]} view={createScheduleWeeklyView({maxHour: 19, minHour: 7})} /> );}Pagination Hotkeys
Section titled “Pagination Hotkeys”Use the left and right arrow keys to move between weeks.
August 2026
Sun23
Mon24
Tue25
Wed26
Thu27
Fri28
Sat29
() => { const [viewDate, setViewDate] = useState<Instant>(() => defaultViewDate); const paginationPlugin = useSchedulePaginationPlugin({ hasHotkeys: true, onViewDateChange: setViewDate, });
return ( <div className={paginationHotkeysStoryContainer}> <Text as="p" color="secondary" type="supporting"> Use the left and right arrow keys to move between weeks. </Text> <Schedule categories={categories} events={weekEvents} highlightDate={defaultHighlightDate} plugins={[paginationPlugin]} timezoneID={localTimezoneID} view={createScheduleWeeklyView({maxHour: 18, minHour: 8})} viewDate={viewDate} /> </div> );}Resizable Events
Section titled “Resizable Events”August 2026
Sun23
Mon24
Tue25
Wed26
Thu27
Fri28
Sat29
function ResizableEventsStory(): React.JSX.Element { const [viewDate, setViewDate] = useState<Instant>(() => defaultViewDate); const [storyEvents, setStoryEvents] = useState(() => events); const paginationPlugin = useSchedulePaginationPlugin({ onViewDateChange: setViewDate, }); const resizePlugin = useScheduleEventResizePlugin({ onResize: ({end, event, start}) => { setStoryEvents(currentEvents => currentEvents.map(currentEvent => { if ( currentEvent.id !== event.id || typeof currentEvent.start !== 'number' ) { return currentEvent; }
return {...currentEvent, end, start}; }), ); }, snapMinutes: 5, });
return ( <Schedule categories={categories} events={storyEvents} highlightDate={defaultHighlightDate} plugins={[paginationPlugin, resizePlugin]} timezoneID={localTimezoneID} view={createScheduleWeeklyView({maxHour: 18, minHour: 8})} viewDate={viewDate} /> );}
<ResizableEventsStory />Movable Events
Section titled “Movable Events”August 2026
Sun23
Mon24
Tue25
Wed26
Thu27
Fri28
Sat29
function MovableEventsStory(): React.JSX.Element { const views = useMemo( (): {label: string; view: ScheduleView}[] => [ {label: 'Month', view: createScheduleMonthlyView()}, { label: 'Week', view: createScheduleWeeklyView({maxHour: 18, minHour: 8}), }, ], [], ); const [view, setView] = useState<ScheduleView>(views[1].view); const [viewDate, setViewDate] = useState<Instant>(() => defaultViewDate); const [storyEvents, setStoryEvents] = useState(() => events); const paginationPlugin = useSchedulePaginationPlugin({ onViewDateChange: setViewDate, }); const viewSelectorPlugin = useScheduleViewSelectorPlugin(views, { onChangeView: setView, }); const movePlugin = useScheduleEventMovePlugin({ onMove: ({end, event, start}) => { setStoryEvents(currentEvents => currentEvents.map(currentEvent => { if (currentEvent.id !== event.id) { return currentEvent; }
if ( typeof currentEvent.start === 'number' && typeof start === 'number' && typeof end === 'number' ) { return {...currentEvent, end, start}; }
if ( typeof currentEvent.start !== 'number' && typeof start !== 'number' && typeof end !== 'number' ) { return {...currentEvent, end, start}; }
return currentEvent; }), ); }, snapMinutes: 5, });
return ( <Schedule categories={categories} events={storyEvents} highlightDate={defaultHighlightDate} plugins={[paginationPlugin, viewSelectorPlugin, movePlugin]} timezoneID={localTimezoneID} view={view} viewDate={viewDate} /> );}
<MovableEventsStory />Creatable Events
Section titled “Creatable Events”August 2026
Sun23
Mon24
Tue25
Wed26
Thu27
Fri28
Sat29
function CreatableEventsStory(): React.JSX.Element { const [viewDate, setViewDate] = useState<Instant>(() => defaultViewDate); const [storyEvents, setStoryEvents] = useState<CalendarEvent[]>(() => events); const paginationPlugin = useSchedulePaginationPlugin({ onViewDateChange: setViewDate, }); const popoverPlugin = useScheduleEventPopoverPlugin(); const createPlugin = useScheduleEventCreatePlugin({ defaultDurationMinutes: 60, renderContent: ({close, draft}) => ( <CreateEventForm draft={draft} onCancel={close} onCreate={title => { setStoryEvents(currentEvents => [ ...currentEvents, { category: 'Sync', end: draft.end, id: `created-${draft.start}`, start: draft.start, title, }, ]); close(); }} /> ), snapMinutes: 15, });
return ( <Schedule categories={categories} events={storyEvents} highlightDate={defaultHighlightDate} plugins={[paginationPlugin, createPlugin, popoverPlugin]} timezoneID={localTimezoneID} view={createScheduleWeeklyView({maxHour: 18, minHour: 8})} viewDate={viewDate} /> );}
function CreateEventForm({ draft, onCancel, onCreate,}: { draft: ScheduleEventDraft; onCancel: () => void; onCreate: (title: string) => void;}): React.JSX.Element { const [title, setTitle] = useState(''); const timeLabel = `${Temporal.Instant.fromEpochMilliseconds(draft.start) .toZonedDateTimeISO(localTimezoneID) .toLocaleString(undefined, { hour: 'numeric', minute: '2-digit', weekday: 'short', })} – ${Temporal.Instant.fromEpochMilliseconds(draft.end) .toZonedDateTimeISO(localTimezoneID) .toLocaleString(undefined, {hour: 'numeric', minute: '2-digit'})}`;
return ( <form className={css({w: 80})} onSubmit={submitEvent => { submitEvent.preventDefault(); onCreate(title.trim() === '' ? 'Untitled event' : title.trim()); }}> <Layout content={ <LayoutContent className={css({display: 'grid', gap: 3})}> <TextInput hasAutoFocus label="Title" onChange={setTitle} placeholder="Add a title" value={title} /> <Text color="secondary" type="supporting"> {timeLabel} </Text> </LayoutContent> } footer={ <LayoutFooter primaryButton={ <Button label="Create" size="sm" type="submit" variant="primary" /> } secondaryButton={ <Button label="Cancel" onClick={onCancel} size="sm" variant="ghost" /> } /> } header={<LayoutHeader title="New event" />} height="auto" /> </form> );}
<CreatableEventsStory />Monday Start Week
Section titled “Monday Start Week”August 2026
Mon24
Tue25
Wed26
Thu27
Fri28
Sat29
Sun30
function ScheduleStory({ categories: storyCategories = categories, events: storyEvents = events, height, highlightDate = defaultHighlightDate, plugins, timezoneID = localTimezoneID, view, viewDate: initialViewDate = defaultViewDate,}: { categories?: ReadonlyArray<ScheduleCategory>; events?: ScheduleEventSource; height?: ScheduleHeight; highlightDate?: Instant; plugins?: SchedulePlugin[]; timezoneID?: string; view: ScheduleView; viewDate?: Instant;}) { const [viewDate, setViewDate] = useState<Instant>(() => initialViewDate); const paginationPlugin = useSchedulePaginationPlugin({ onViewDateChange: setViewDate, }); return ( <Schedule categories={storyCategories} events={storyEvents} height={height} highlightDate={highlightDate} plugins={plugins ?? [paginationPlugin]} timezoneID={timezoneID} view={view} viewDate={viewDate} /> );}
<ScheduleStory view={createScheduleWeeklyView({ maxHour: 18, minHour: 8, weekStartsOn: 1, })}/>Hidden Weekend Days
Section titled “Hidden Weekend Days”August 2026
Mon24
Tue25
Wed26
Thu27
Fri28
function ScheduleStory({ categories: storyCategories = categories, events: storyEvents = events, height, highlightDate = defaultHighlightDate, plugins, timezoneID = localTimezoneID, view, viewDate: initialViewDate = defaultViewDate,}: { categories?: ReadonlyArray<ScheduleCategory>; events?: ScheduleEventSource; height?: ScheduleHeight; highlightDate?: Instant; plugins?: SchedulePlugin[]; timezoneID?: string; view: ScheduleView; viewDate?: Instant;}) { const [viewDate, setViewDate] = useState<Instant>(() => initialViewDate); const paginationPlugin = useSchedulePaginationPlugin({ onViewDateChange: setViewDate, }); return ( <Schedule categories={storyCategories} events={storyEvents} height={height} highlightDate={highlightDate} plugins={plugins ?? [paginationPlugin]} timezoneID={timezoneID} view={view} viewDate={viewDate} /> );}
<ScheduleStory events={weekEvents} view={createScheduleWeeklyView({ hiddenDays: [0, 6], maxHour: 18, minHour: 8, })}/>August 2026
Tue25
function ScheduleStory({ categories: storyCategories = categories, events: storyEvents = events, height, highlightDate = defaultHighlightDate, plugins, timezoneID = localTimezoneID, view, viewDate: initialViewDate = defaultViewDate,}: { categories?: ReadonlyArray<ScheduleCategory>; events?: ScheduleEventSource; height?: ScheduleHeight; highlightDate?: Instant; plugins?: SchedulePlugin[]; timezoneID?: string; view: ScheduleView; viewDate?: Instant;}) { const [viewDate, setViewDate] = useState<Instant>(() => initialViewDate); const paginationPlugin = useSchedulePaginationPlugin({ onViewDateChange: setViewDate, }); return ( <Schedule categories={storyCategories} events={storyEvents} height={height} highlightDate={highlightDate} plugins={plugins ?? [paginationPlugin]} timezoneID={timezoneID} view={view} viewDate={viewDate} /> );}
<ScheduleStory view={createScheduleDayView({maxHour: 18, minHour: 8})} />Overlapping Events Side By Side
Section titled “Overlapping Events Side By Side”August 2026
Tue25
function ScheduleStory({ categories: storyCategories = categories, events: storyEvents = events, height, highlightDate = defaultHighlightDate, plugins, timezoneID = localTimezoneID, view, viewDate: initialViewDate = defaultViewDate,}: { categories?: ReadonlyArray<ScheduleCategory>; events?: ScheduleEventSource; height?: ScheduleHeight; highlightDate?: Instant; plugins?: SchedulePlugin[]; timezoneID?: string; view: ScheduleView; viewDate?: Instant;}) { const [viewDate, setViewDate] = useState<Instant>(() => initialViewDate); const paginationPlugin = useSchedulePaginationPlugin({ onViewDateChange: setViewDate, }); return ( <Schedule categories={storyCategories} events={storyEvents} height={height} highlightDate={highlightDate} plugins={plugins ?? [paginationPlugin]} timezoneID={timezoneID} view={view} viewDate={viewDate} /> );}
<ScheduleStory events={overlappingEvents} view={createScheduleDayView({maxHour: 16, minHour: 8})}/>Overlapping Events Indented
Section titled “Overlapping Events Indented”August 2026
Tue25
function ScheduleStory({ categories: storyCategories = categories, events: storyEvents = events, height, highlightDate = defaultHighlightDate, plugins, timezoneID = localTimezoneID, view, viewDate: initialViewDate = defaultViewDate,}: { categories?: ReadonlyArray<ScheduleCategory>; events?: ScheduleEventSource; height?: ScheduleHeight; highlightDate?: Instant; plugins?: SchedulePlugin[]; timezoneID?: string; view: ScheduleView; viewDate?: Instant;}) { const [viewDate, setViewDate] = useState<Instant>(() => initialViewDate); const paginationPlugin = useSchedulePaginationPlugin({ onViewDateChange: setViewDate, }); return ( <Schedule categories={storyCategories} events={storyEvents} height={height} highlightDate={highlightDate} plugins={plugins ?? [paginationPlugin]} timezoneID={timezoneID} view={view} viewDate={viewDate} /> );}
<ScheduleStory events={overlappingEvents} view={createScheduleDayView({ maxHour: 16, minHour: 8, overlapBehavior: 'indented', })}/>List View
Section titled “List View”August 2026
25Tue
function ScheduleStory({ categories: storyCategories = categories, events: storyEvents = events, height, highlightDate = defaultHighlightDate, plugins, timezoneID = localTimezoneID, view, viewDate: initialViewDate = defaultViewDate,}: { categories?: ReadonlyArray<ScheduleCategory>; events?: ScheduleEventSource; height?: ScheduleHeight; highlightDate?: Instant; plugins?: SchedulePlugin[]; timezoneID?: string; view: ScheduleView; viewDate?: Instant;}) { const [viewDate, setViewDate] = useState<Instant>(() => initialViewDate); const paginationPlugin = useSchedulePaginationPlugin({ onViewDateChange: setViewDate, }); return ( <Schedule categories={storyCategories} events={storyEvents} height={height} highlightDate={highlightDate} plugins={plugins ?? [paginationPlugin]} timezoneID={timezoneID} view={view} viewDate={viewDate} /> );}
() => { const now = Temporal.Now.instant(); const timezoneID = Intl.DateTimeFormat().resolvedOptions().timeZone; const listEvents = [ createEventFromISO({ category: 'Sync', end: now.subtract({minutes: 90}).toString(), id: 'list-past-sync', start: now.subtract({minutes: 150}).toString(), title: 'Past sync', }), createEventFromISO({ category: 'Customer', end: now.subtract({minutes: 20}).toString(), id: 'list-past-escalation', start: now.subtract({minutes: 80}).toString(), title: 'Customer escalation review', }), createEventFromISO({ category: 'Design', end: now.add({minutes: 45}).toString(), id: 'list-current-review', start: now.subtract({minutes: 15}).toString(), title: 'Current design review', }), createEventFromISO({ category: 'Planning', end: now.add({minutes: 135}).toString(), id: 'list-future-planning', start: now.add({minutes: 75}).toString(), title: 'Future planning session', }), createEventFromISO({ category: 'Operations', end: now.add({minutes: 240}).toString(), id: 'list-future-release', start: now.add({minutes: 180}).toString(), title: 'Release readiness', }), ];
return ( <ScheduleStory events={listEvents} highlightDate={now.epochMilliseconds} timezoneID={timezoneID} view={createScheduleListView({days: 7})} viewDate={now.epochMilliseconds} /> );}Async Events
Section titled “Async Events”August 2026
Sun23
Mon24
Tue25
Wed26
Thu27
Fri28
Sat29
function ScheduleStory({ categories: storyCategories = categories, events: storyEvents = events, height, highlightDate = defaultHighlightDate, plugins, timezoneID = localTimezoneID, view, viewDate: initialViewDate = defaultViewDate,}: { categories?: ReadonlyArray<ScheduleCategory>; events?: ScheduleEventSource; height?: ScheduleHeight; highlightDate?: Instant; plugins?: SchedulePlugin[]; timezoneID?: string; view: ScheduleView; viewDate?: Instant;}) { const [viewDate, setViewDate] = useState<Instant>(() => initialViewDate); const paginationPlugin = useSchedulePaginationPlugin({ onViewDateChange: setViewDate, }); return ( <Schedule categories={storyCategories} events={storyEvents} height={height} highlightDate={highlightDate} plugins={plugins ?? [paginationPlugin]} timezoneID={timezoneID} view={view} viewDate={viewDate} /> );}
() => { const loader = useMemo<ScheduleEventSource>( () => async () => new Promise(resolve => { setTimeout(() => resolve(events), 900); }), [], );
return ( <ScheduleStory events={loader} view={createScheduleWeeklyView({maxHour: 18, minHour: 8})} /> );}Async Events With Toast Error
Section titled “Async Events With Toast Error”August 2026
Sun23
Mon24
Tue25
Wed26
Thu27
Fri28
Sat29
function AsyncEventsWithToastStory(): React.JSX.Element { const toast = useToast(); const loader = useMemo<ScheduleEventSource>( () => async () => { try { await new Promise((_, reject) => { setTimeout(() => reject(new Error('Unable to load events')), 900); }); return []; } catch { toast({ body: 'Unable to load schedule events', type: 'error', uniqueID: 'schedule-events-load-error', }); return []; } }, [toast], );
return ( <ScheduleStory events={loader} view={createScheduleWeeklyView({maxHour: 18, minHour: 8})} /> );}
function ScheduleStory({ categories: storyCategories = categories, events: storyEvents = events, height, highlightDate = defaultHighlightDate, plugins, timezoneID = localTimezoneID, view, viewDate: initialViewDate = defaultViewDate,}: { categories?: ReadonlyArray<ScheduleCategory>; events?: ScheduleEventSource; height?: ScheduleHeight; highlightDate?: Instant; plugins?: SchedulePlugin[]; timezoneID?: string; view: ScheduleView; viewDate?: Instant;}) { const [viewDate, setViewDate] = useState<Instant>(() => initialViewDate); const paginationPlugin = useSchedulePaginationPlugin({ onViewDateChange: setViewDate, }); return ( <Schedule categories={storyCategories} events={storyEvents} height={height} highlightDate={highlightDate} plugins={plugins ?? [paginationPlugin]} timezoneID={timezoneID} view={view} viewDate={viewDate} /> );}
<ToastViewport> <AsyncEventsWithToastStory /></ToastViewport>View Selector
Section titled “View Selector”August 2026
Sun23
Mon24
Tue25
Wed26
Thu27
Fri28
Sat29
function ScheduleStory({ categories: storyCategories = categories, events: storyEvents = events, height, highlightDate = defaultHighlightDate, plugins, timezoneID = localTimezoneID, view, viewDate: initialViewDate = defaultViewDate,}: { categories?: ReadonlyArray<ScheduleCategory>; events?: ScheduleEventSource; height?: ScheduleHeight; highlightDate?: Instant; plugins?: SchedulePlugin[]; timezoneID?: string; view: ScheduleView; viewDate?: Instant;}) { const [viewDate, setViewDate] = useState<Instant>(() => initialViewDate); const paginationPlugin = useSchedulePaginationPlugin({ onViewDateChange: setViewDate, }); return ( <Schedule categories={storyCategories} events={storyEvents} height={height} highlightDate={highlightDate} plugins={plugins ?? [paginationPlugin]} timezoneID={timezoneID} view={view} viewDate={viewDate} /> );}
() => { const views = useMemo( (): ScheduleViewSelectorOption[] => [ {hotkey: 'm', label: 'Month', view: createScheduleMonthlyView()}, { hotkey: 'w', label: 'Week', view: createScheduleWeeklyView({maxHour: 18, minHour: 8}), }, { hotkey: 'd', label: 'Day', view: createScheduleDayView({maxHour: 18, minHour: 8}), }, {hotkey: 'l', label: 'List', view: createScheduleListView({days: 7})}, ], [], ); const [view, setView] = useState<ScheduleView>(views[1].view); const viewSelectorPlugin = useScheduleViewSelectorPlugin(views, { onChangeView: setView, });
return <ScheduleStory plugins={[viewSelectorPlugin]} view={view} />;}Fill Height
Section titled “Fill Height”August 2026
Sun23
Mon24
Tue25
Wed26
Thu27
Fri28
Sat29
() => { const views = useMemo( (): {label: string; view: ScheduleView}[] => [ {label: 'Month', view: createScheduleMonthlyView()}, { label: 'Week', view: createScheduleWeeklyView({maxHour: 18, minHour: 8}), }, {label: 'Day', view: createScheduleDayView({maxHour: 18, minHour: 8})}, {label: 'List', view: createScheduleListView({days: 7})}, ], [], ); const [view, setView] = useState<ScheduleView>(views[1].view); const [viewDate, setViewDate] = useState<Instant>(() => defaultViewDate); const paginationPlugin = useSchedulePaginationPlugin({ onViewDateChange: setViewDate, }); const viewSelectorPlugin = useScheduleViewSelectorPlugin(views, { onChangeView: setView, });
return ( <div className={fillHeightStoryContainer}> <Schedule categories={categories} events={events} height="fill" highlightDate={defaultHighlightDate} plugins={[paginationPlugin, viewSelectorPlugin]} timezoneID={localTimezoneID} view={view} viewDate={viewDate} /> </div> );}Fill Height With Surplus Space
Section titled “Fill Height With Surplus Space”August 2026
Sun23
Mon24
Tue25
Wed26
Thu27
Fri28
Sat29
function ScheduleStory({ categories: storyCategories = categories, events: storyEvents = events, height, highlightDate = defaultHighlightDate, plugins, timezoneID = localTimezoneID, view, viewDate: initialViewDate = defaultViewDate,}: { categories?: ReadonlyArray<ScheduleCategory>; events?: ScheduleEventSource; height?: ScheduleHeight; highlightDate?: Instant; plugins?: SchedulePlugin[]; timezoneID?: string; view: ScheduleView; viewDate?: Instant;}) { const [viewDate, setViewDate] = useState<Instant>(() => initialViewDate); const paginationPlugin = useSchedulePaginationPlugin({ onViewDateChange: setViewDate, }); return ( <Schedule categories={storyCategories} events={storyEvents} height={height} highlightDate={highlightDate} plugins={plugins ?? [paginationPlugin]} timezoneID={timezoneID} view={view} viewDate={viewDate} /> );}
<div className={fillHeightStoryContainer}> <ScheduleStory height="fill" view={createScheduleWeeklyView({maxHour: 10, minHour: 8})} /></div>Custom Plugin
Section titled “Custom Plugin”August 2026
Sun23
Mon24
Tue25
Wed26
Thu27
Fri28
Sat29
function ScheduleStory({ categories: storyCategories = categories, events: storyEvents = events, height, highlightDate = defaultHighlightDate, plugins, timezoneID = localTimezoneID, view, viewDate: initialViewDate = defaultViewDate,}: { categories?: ReadonlyArray<ScheduleCategory>; events?: ScheduleEventSource; height?: ScheduleHeight; highlightDate?: Instant; plugins?: SchedulePlugin[]; timezoneID?: string; view: ScheduleView; viewDate?: Instant;}) { const [viewDate, setViewDate] = useState<Instant>(() => initialViewDate); const paginationPlugin = useSchedulePaginationPlugin({ onViewDateChange: setViewDate, }); return ( <Schedule categories={storyCategories} events={storyEvents} height={height} highlightDate={highlightDate} plugins={plugins ?? [paginationPlugin]} timezoneID={timezoneID} view={view} viewDate={viewDate} /> );}
() => { const customPlugin = useMemo<SchedulePlugin>( () => ({ renderHeader(startContent, centerContent, endContent) { return { centerContent, endContent: ( <> {endContent} <Button label="Export" /> </> ), startContent: ( <> {startContent} <Badge color="info" label="Draft" size="sm" /> </> ), }; }, }), [], );
return ( <ScheduleStory plugins={[customPlugin]} view={createScheduleWeeklyView({maxHour: 18, minHour: 8})} /> );}Event End Content Plugin
Section titled “Event End Content Plugin”August 2026
Sun
Mon
Tue
Wed
Thu
Fri
Sat
function ScheduleStory({ categories: storyCategories = categories, events: storyEvents = events, height, highlightDate = defaultHighlightDate, plugins, timezoneID = localTimezoneID, view, viewDate: initialViewDate = defaultViewDate,}: { categories?: ReadonlyArray<ScheduleCategory>; events?: ScheduleEventSource; height?: ScheduleHeight; highlightDate?: Instant; plugins?: SchedulePlugin[]; timezoneID?: string; view: ScheduleView; viewDate?: Instant;}) { const [viewDate, setViewDate] = useState<Instant>(() => initialViewDate); const paginationPlugin = useSchedulePaginationPlugin({ onViewDateChange: setViewDate, }); return ( <Schedule categories={storyCategories} events={storyEvents} height={height} highlightDate={highlightDate} plugins={plugins ?? [paginationPlugin]} timezoneID={timezoneID} view={view} viewDate={viewDate} /> );}
() => { const views = useMemo( (): ScheduleViewSelectorOption[] => [ {label: 'Month', view: createScheduleMonthlyView()}, { label: 'Week', view: createScheduleWeeklyView({maxHour: 18, minHour: 8}), }, {label: 'List', view: createScheduleListView({days: 7})}, ], [], ); const [view, setView] = useState<ScheduleView>(views[0].view); const viewSelectorPlugin = useScheduleViewSelectorPlugin(views, { onChangeView: setView, }); const statusPlugin = useMemo<SchedulePlugin>( () => ({ renderEventEndContent: ({event}) => { if (event.id === 'customer-escalation') { return ( <Tooltip content="Needs attention" hoverIndication="never"> <span aria-label="Needs attention" role="img"> <Icon color="warning" icon={TriangleAlert} size="sm" /> </span> </Tooltip> ); } return event.id === 'offsite' ? ( <Tooltip content="Confirmed" hoverIndication="never"> <span aria-label="Confirmed" role="img"> <Icon color="success" icon={CircleCheck} size="sm" /> </span> </Tooltip> ) : null; }, }), [], ); const recurrencePlugin = useMemo<SchedulePlugin>( () => ({ renderEventEndContent: ({event}) => event.category === 'Planning' ? ( <Tooltip content="Recurring" hoverIndication="never"> <span aria-label="Recurring" role="img"> <Icon icon={Repeat2} size="sm" /> </span> </Tooltip> ) : null, }), [], );
return ( <ScheduleStory plugins={[viewSelectorPlugin, statusPlugin, recurrencePlugin]} view={view} /> );}Event Popover
Section titled “Event Popover”August 2026
Sun
Mon
Tue
Wed
Thu
Fri
Sat
function EventPopoverStory(): React.JSX.Element { const views = useMemo( (): {label: string; view: ScheduleView}[] => [ {label: 'Month', view: createScheduleMonthlyView()}, { label: 'Week', view: createScheduleWeeklyView({maxHour: 18, minHour: 8}), }, {label: 'Day', view: createScheduleDayView({maxHour: 18, minHour: 8})}, {label: 'List', view: createScheduleListView({days: 7})}, ], [], ); const [view, setView] = useState<ScheduleView>(views[0].view); const [viewDate, setViewDate] = useState<Instant>(() => defaultViewDate); const paginationPlugin = useSchedulePaginationPlugin({ onViewDateChange: setViewDate, }); const viewSelectorPlugin = useScheduleViewSelectorPlugin(views, { onChangeView: setView, }); const eventPopoverPlugin = useScheduleEventPopoverPlugin({ renderContent: ({event, close}) => ( <ScheduleEventPopoverContent event={event} onClose={close} onDelete={e => window.alert(`Delete ${e.title}`)} onEdit={e => window.alert(`Edit ${e.title}`)} onRespond={(e, response) => window.alert(`${response} for ${e.title}`)} /> ), }); return ( <Schedule categories={categories} events={eventPopoverEvents} highlightDate={defaultHighlightDate} plugins={[paginationPlugin, viewSelectorPlugin, eventPopoverPlugin]} timezoneID={localTimezoneID} view={view} viewDate={viewDate} /> );}
<EventPopoverStory />Event Popover Custom Content
Section titled “Event Popover Custom Content”August 2026
Sun23
Mon24
Tue25
Wed26
Thu27
Fri28
Sat29
() => { const [viewDate, setViewDate] = useState<Instant>(() => defaultViewDate); const paginationPlugin = useSchedulePaginationPlugin({ onViewDateChange: setViewDate, }); const eventPopoverPlugin = useScheduleEventPopoverPlugin({ hasCloseButton: true, renderContent: ({event}) => ( <Layout className={css({w: '64'})} content={ <LayoutContent padding={4}> <Badge color="info" label={event.category ?? 'Event'} size="sm" /> </LayoutContent> } header={<LayoutHeader title={event.title} />} height="auto" /> ), }); return ( <Schedule categories={categories} events={eventPopoverEvents} highlightDate={defaultHighlightDate} plugins={[paginationPlugin, eventPopoverPlugin]} timezoneID={localTimezoneID} view={createScheduleWeeklyView({maxHour: 18, minHour: 8})} viewDate={viewDate} /> );}Without Categories
Section titled “Without Categories”August 2026
Sun23
Mon24
Tue25
Wed26
Thu27
Fri28
Sat29
function ScheduleStory({ categories: storyCategories = categories, events: storyEvents = events, height, highlightDate = defaultHighlightDate, plugins, timezoneID = localTimezoneID, view, viewDate: initialViewDate = defaultViewDate,}: { categories?: ReadonlyArray<ScheduleCategory>; events?: ScheduleEventSource; height?: ScheduleHeight; highlightDate?: Instant; plugins?: SchedulePlugin[]; timezoneID?: string; view: ScheduleView; viewDate?: Instant;}) { const [viewDate, setViewDate] = useState<Instant>(() => initialViewDate); const paginationPlugin = useSchedulePaginationPlugin({ onViewDateChange: setViewDate, }); return ( <Schedule categories={storyCategories} events={storyEvents} height={height} highlightDate={highlightDate} plugins={plugins ?? [paginationPlugin]} timezoneID={timezoneID} view={view} viewDate={viewDate} /> );}
<ScheduleStory categories={[]} events={eventsWithoutCategories} view={createScheduleWeeklyView({maxHour: 18, minHour: 8})}/>Color And Category Fallbacks
Section titled “Color And Category Fallbacks”August 2026
Sun23
Mon24
Tue25
Wed26
Thu27
Fri28
Sat29
function ScheduleStory({ categories: storyCategories = categories, events: storyEvents = events, height, highlightDate = defaultHighlightDate, plugins, timezoneID = localTimezoneID, view, viewDate: initialViewDate = defaultViewDate,}: { categories?: ReadonlyArray<ScheduleCategory>; events?: ScheduleEventSource; height?: ScheduleHeight; highlightDate?: Instant; plugins?: SchedulePlugin[]; timezoneID?: string; view: ScheduleView; viewDate?: Instant;}) { const [viewDate, setViewDate] = useState<Instant>(() => initialViewDate); const paginationPlugin = useSchedulePaginationPlugin({ onViewDateChange: setViewDate, }); return ( <Schedule categories={storyCategories} events={storyEvents} height={height} highlightDate={highlightDate} plugins={plugins ?? [paginationPlugin]} timezoneID={timezoneID} view={view} viewDate={viewDate} /> );}
() => { const fallbackEvents = [ ...colorFallbackCategories.map((category, index) => createEventFromISO({ category: category.label, end: timedISO(0, index + 9, 30), id: `color-${category.color}`, start: timedISO(0, index + 9), title: `${category.label} category`, }), ), createEventFromISO({ category: 'Unmapped', end: timedISO(1, 15, 30), id: 'unknown-category', start: timedISO(1, 15), title: 'Unknown category keeps label', }), createEventFromISO({ end: timedISO(1, 16, 30), id: 'missing-category', start: timedISO(1, 16), title: 'Missing category uses default', }), ];
return ( <ScheduleStory categories={colorFallbackCategories} events={fallbackEvents} view={createScheduleWeeklyView({maxHour: 20, minHour: 8})} /> );}August 2026
25Tue
function ScheduleStory({ categories: storyCategories = categories, events: storyEvents = events, height, highlightDate = defaultHighlightDate, plugins, timezoneID = localTimezoneID, view, viewDate: initialViewDate = defaultViewDate,}: { categories?: ReadonlyArray<ScheduleCategory>; events?: ScheduleEventSource; height?: ScheduleHeight; highlightDate?: Instant; plugins?: SchedulePlugin[]; timezoneID?: string; view: ScheduleView; viewDate?: Instant;}) { const [viewDate, setViewDate] = useState<Instant>(() => initialViewDate); const paginationPlugin = useSchedulePaginationPlugin({ onViewDateChange: setViewDate, }); return ( <Schedule categories={storyCategories} events={storyEvents} height={height} highlightDate={highlightDate} plugins={plugins ?? [paginationPlugin]} timezoneID={timezoneID} view={view} viewDate={viewDate} /> );}
<ScheduleStory events={[]} view={createScheduleListView({days: 7})} />Multi Day Events
Section titled “Multi Day Events”August 2026
Sun23
Mon24
Tue25
Wed26
Thu27
Fri28
Sat29
function ScheduleStory({ categories: storyCategories = categories, events: storyEvents = events, height, highlightDate = defaultHighlightDate, plugins, timezoneID = localTimezoneID, view, viewDate: initialViewDate = defaultViewDate,}: { categories?: ReadonlyArray<ScheduleCategory>; events?: ScheduleEventSource; height?: ScheduleHeight; highlightDate?: Instant; plugins?: SchedulePlugin[]; timezoneID?: string; view: ScheduleView; viewDate?: Instant;}) { const [viewDate, setViewDate] = useState<Instant>(() => initialViewDate); const paginationPlugin = useSchedulePaginationPlugin({ onViewDateChange: setViewDate, }); return ( <Schedule categories={storyCategories} events={storyEvents} height={height} highlightDate={highlightDate} plugins={plugins ?? [paginationPlugin]} timezoneID={timezoneID} view={view} viewDate={viewDate} /> );}
<ScheduleStory events={multiDayEvents} view={createScheduleWeeklyView({maxHour: 24, minHour: 0})}/>Timezones
Section titled “Timezones”August 2026
Tue25
August 2026
Tue25
function ScheduleStory({ categories: storyCategories = categories, events: storyEvents = events, height, highlightDate = defaultHighlightDate, plugins, timezoneID = localTimezoneID, view, viewDate: initialViewDate = defaultViewDate,}: { categories?: ReadonlyArray<ScheduleCategory>; events?: ScheduleEventSource; height?: ScheduleHeight; highlightDate?: Instant; plugins?: SchedulePlugin[]; timezoneID?: string; view: ScheduleView; viewDate?: Instant;}) { const [viewDate, setViewDate] = useState<Instant>(() => initialViewDate); const paginationPlugin = useSchedulePaginationPlugin({ onViewDateChange: setViewDate, }); return ( <Schedule categories={storyCategories} events={storyEvents} height={height} highlightDate={highlightDate} plugins={plugins ?? [paginationPlugin]} timezoneID={timezoneID} view={view} viewDate={viewDate} /> );}
() => { // Anchored to a fixed UTC time-of-day (not the viewer's local zone) so the // same instant is shown side by side in two zones deterministically. const utcToday = Temporal.Now.plainDateISO('UTC'); const utcInstant = (hour: number): string => utcToday .toZonedDateTime({ plainTime: Temporal.PlainTime.from({hour}), timeZone: 'UTC', }) .toInstant() .toString(); const sameInstantEvents = [ createEventFromISO({ category: 'Sync', end: utcInstant(19), id: 'global-sync', start: utcInstant(17), title: 'Global sync', }), ];
return ( <div style={{display: 'grid', gap: 24}}> <ScheduleStory events={sameInstantEvents} timezoneID="UTC" view={createScheduleDayView({maxHour: 20, minHour: 8})} viewDate={utcToday.toZonedDateTime('UTC').epochMilliseconds} /> <ScheduleStory events={sameInstantEvents} timezoneID="America/Los_Angeles" view={createScheduleDayView({maxHour: 20, minHour: 8})} viewDate={ utcToday.toZonedDateTime('America/Los_Angeles').epochMilliseconds } /> </div> );}Hour Range Edge Cases
Section titled “Hour Range Edge Cases”August 2026
Tue25
August 2026
Tue25
function ScheduleStory({ categories: storyCategories = categories, events: storyEvents = events, height, highlightDate = defaultHighlightDate, plugins, timezoneID = localTimezoneID, view, viewDate: initialViewDate = defaultViewDate,}: { categories?: ReadonlyArray<ScheduleCategory>; events?: ScheduleEventSource; height?: ScheduleHeight; highlightDate?: Instant; plugins?: SchedulePlugin[]; timezoneID?: string; view: ScheduleView; viewDate?: Instant;}) { const [viewDate, setViewDate] = useState<Instant>(() => initialViewDate); const paginationPlugin = useSchedulePaginationPlugin({ onViewDateChange: setViewDate, }); return ( <Schedule categories={storyCategories} events={storyEvents} height={height} highlightDate={highlightDate} plugins={plugins ?? [paginationPlugin]} timezoneID={timezoneID} view={view} viewDate={viewDate} /> );}
<div style={{display: 'grid', gap: 24}}> <ScheduleStory view={createScheduleDayView({maxHour: 24, minHour: 0})} /> <ScheduleStory view={createScheduleDayView({maxHour: 24, minHour: 20})} /></div>Hour Heights
Section titled “Hour Heights”August 2026
Tue25
August 2026
Sun23
Mon24
Tue25
Wed26
Thu27
Fri28
Sat29
function ScheduleStory({ categories: storyCategories = categories, events: storyEvents = events, height, highlightDate = defaultHighlightDate, plugins, timezoneID = localTimezoneID, view, viewDate: initialViewDate = defaultViewDate,}: { categories?: ReadonlyArray<ScheduleCategory>; events?: ScheduleEventSource; height?: ScheduleHeight; highlightDate?: Instant; plugins?: SchedulePlugin[]; timezoneID?: string; view: ScheduleView; viewDate?: Instant;}) { const [viewDate, setViewDate] = useState<Instant>(() => initialViewDate); const paginationPlugin = useSchedulePaginationPlugin({ onViewDateChange: setViewDate, }); return ( <Schedule categories={storyCategories} events={storyEvents} height={height} highlightDate={highlightDate} plugins={plugins ?? [paginationPlugin]} timezoneID={timezoneID} view={view} viewDate={viewDate} /> );}
<div style={{display: 'grid', gap: 24}}> <ScheduleStory view={createScheduleDayView({ hourHeight: 48, maxHour: 18, minHour: 8, })} /> <ScheduleStory view={createScheduleWeeklyView({ hourHeight: 132, maxHour: 18, minHour: 8, })} /></div>Current Time
Section titled “Current Time”August 2026
Tue25
function ScheduleStory({ categories: storyCategories = categories, events: storyEvents = events, height, highlightDate = defaultHighlightDate, plugins, timezoneID = localTimezoneID, view, viewDate: initialViewDate = defaultViewDate,}: { categories?: ReadonlyArray<ScheduleCategory>; events?: ScheduleEventSource; height?: ScheduleHeight; highlightDate?: Instant; plugins?: SchedulePlugin[]; timezoneID?: string; view: ScheduleView; viewDate?: Instant;}) { const [viewDate, setViewDate] = useState<Instant>(() => initialViewDate); const paginationPlugin = useSchedulePaginationPlugin({ onViewDateChange: setViewDate, }); return ( <Schedule categories={storyCategories} events={storyEvents} height={height} highlightDate={highlightDate} plugins={plugins ?? [paginationPlugin]} timezoneID={timezoneID} view={view} viewDate={viewDate} /> );}
() => { const now = Temporal.Now.instant(); const currentEvents = [ createEventFromISO({ category: 'Sync', end: now.subtract({minutes: 30}).toString(), id: 'past-sync', start: now.subtract({minutes: 90}).toString(), title: 'Past sync', }), createEventFromISO({ category: 'Design', end: now.add({minutes: 90}).toString(), id: 'active-review', start: now.add({minutes: 30}).toString(), title: 'Design review', }), ];
return ( <ScheduleStory events={currentEvents} highlightDate={now.epochMilliseconds} view={createScheduleDayView({maxHour: 24, minHour: 0})} viewDate={now.epochMilliseconds} /> );}Current Time24 Hour Mode
Section titled “Current Time24 Hour Mode”August 2026
Tue25
function ScheduleStory({ categories: storyCategories = categories, events: storyEvents = events, height, highlightDate = defaultHighlightDate, plugins, timezoneID = localTimezoneID, view, viewDate: initialViewDate = defaultViewDate,}: { categories?: ReadonlyArray<ScheduleCategory>; events?: ScheduleEventSource; height?: ScheduleHeight; highlightDate?: Instant; plugins?: SchedulePlugin[]; timezoneID?: string; view: ScheduleView; viewDate?: Instant;}) { const [viewDate, setViewDate] = useState<Instant>(() => initialViewDate); const paginationPlugin = useSchedulePaginationPlugin({ onViewDateChange: setViewDate, }); return ( <Schedule categories={storyCategories} events={storyEvents} height={height} highlightDate={highlightDate} plugins={plugins ?? [paginationPlugin]} timezoneID={timezoneID} view={view} viewDate={viewDate} /> );}
() => { const now = Temporal.Now.instant(); const timezoneID = Intl.DateTimeFormat().resolvedOptions().timeZone; const currentEvents = [ createEventFromISO({ category: 'Sync', end: now.subtract({minutes: 15}).toString(), id: 'current-24-past', start: now.subtract({minutes: 75}).toString(), title: 'Earlier sync', }), createEventFromISO({ category: 'Design', end: now.add({minutes: 90}).toString(), id: 'current-24-next', start: now.add({minutes: 30}).toString(), title: 'Upcoming review', }), ];
return ( <ScheduleStory events={currentEvents} highlightDate={now.epochMilliseconds} timezoneID={timezoneID} view={createScheduleDayView({ hourHeight: 56, maxHour: 24, minHour: 0, })} viewDate={now.epochMilliseconds} /> );}Past And Current States
Section titled “Past And Current States”August 2026
Tue25
function ScheduleStory({ categories: storyCategories = categories, events: storyEvents = events, height, highlightDate = defaultHighlightDate, plugins, timezoneID = localTimezoneID, view, viewDate: initialViewDate = defaultViewDate,}: { categories?: ReadonlyArray<ScheduleCategory>; events?: ScheduleEventSource; height?: ScheduleHeight; highlightDate?: Instant; plugins?: SchedulePlugin[]; timezoneID?: string; view: ScheduleView; viewDate?: Instant;}) { const [viewDate, setViewDate] = useState<Instant>(() => initialViewDate); const paginationPlugin = useSchedulePaginationPlugin({ onViewDateChange: setViewDate, }); return ( <Schedule categories={storyCategories} events={storyEvents} height={height} highlightDate={highlightDate} plugins={plugins ?? [paginationPlugin]} timezoneID={timezoneID} view={view} viewDate={viewDate} /> );}
() => { const now = Temporal.Now.instant(); const stateEvents = [ createEventFromISO({ category: 'Sync', end: now.subtract({minutes: 45}).toString(), id: 'past-state', start: now.subtract({minutes: 105}).toString(), title: 'Past event', }), createEventFromISO({ category: 'Design', end: now.add({minutes: 30}).toString(), id: 'current-state', start: now.subtract({minutes: 30}).toString(), title: 'Current event', }), createEventFromISO({ category: 'Planning', end: now.add({minutes: 120}).toString(), id: 'future-state', start: now.add({minutes: 60}).toString(), title: 'Future event', }), ];
return ( <ScheduleStory events={stateEvents} highlightDate={now.epochMilliseconds} view={createScheduleDayView({maxHour: 24, minHour: 0})} viewDate={now.epochMilliseconds} /> );}Highlight Date
Section titled “Highlight Date”August 2026
Sun23
Mon24
Tue25
Wed26
Thu27
Fri28
Sat29
function ScheduleStory({ categories: storyCategories = categories, events: storyEvents = events, height, highlightDate = defaultHighlightDate, plugins, timezoneID = localTimezoneID, view, viewDate: initialViewDate = defaultViewDate,}: { categories?: ReadonlyArray<ScheduleCategory>; events?: ScheduleEventSource; height?: ScheduleHeight; highlightDate?: Instant; plugins?: SchedulePlugin[]; timezoneID?: string; view: ScheduleView; viewDate?: Instant;}) { const [viewDate, setViewDate] = useState<Instant>(() => initialViewDate); const paginationPlugin = useSchedulePaginationPlugin({ onViewDateChange: setViewDate, }); return ( <Schedule categories={storyCategories} events={storyEvents} height={height} highlightDate={highlightDate} plugins={plugins ?? [paginationPlugin]} timezoneID={timezoneID} view={view} viewDate={viewDate} /> );}
<ScheduleStory highlightDate={dayInstant(2)} view={createScheduleWeeklyView({maxHour: 18, minHour: 8})} viewDate={dayInstant(0)}/>Highlighted Day Numbers
Section titled “Highlighted Day Numbers”Day 1
May 2026
Fri1
Day 2
May 2026
Sat2
Day 3
May 2026
Sun3
Day 4
May 2026
Mon4
Day 5
May 2026
Tue5
Day 6
May 2026
Wed6
Day 7
May 2026
Thu7
Day 8
May 2026
Fri8
Day 9
May 2026
Sat9
Day 10
May 2026
Sun10
Day 11
May 2026
Mon11
Day 12
May 2026
Tue12
Day 13
May 2026
Wed13
Day 14
May 2026
Thu14
Day 15
May 2026
Fri15
Day 16
May 2026
Sat16
Day 17
May 2026
Sun17
Day 18
May 2026
Mon18
Day 19
May 2026
Tue19
Day 20
May 2026
Wed20
Day 21
May 2026
Thu21
Day 22
May 2026
Fri22
Day 23
May 2026
Sat23
Day 24
May 2026
Sun24
Day 25
May 2026
Mon25
Day 26
May 2026
Tue26
Day 27
May 2026
Wed27
Day 28
May 2026
Thu28
Day 29
May 2026
Fri29
Day 30
May 2026
Sat30
Day 31
May 2026
Sun31
() => { const highlightedDays = Array.from({length: 31}, (_, index) => Temporal.PlainDate.from({ day: index + 1, month: 5, year: 2026, }).toZonedDateTime('UTC'), ); const view = createScheduleDayView({maxHour: 9, minHour: 8});
return ( <div className={highlightedDayNumberGrid}> {highlightedDays.map(day => { const instant = day.epochMilliseconds; return ( <div className={highlightedDayNumberExample} key={day.toString()}> <Text as="p" weight="bold"> Day {day.day} </Text> <Schedule events={[]} highlightDate={instant} plugins={[]} timezoneID="UTC" view={view} viewDate={instant} /> </div> ); })} </div> );}Automatic Month Rows
Section titled “Automatic Month Rows”July 2025
Sun
Mon
Tue
Wed
Thu
Fri
Sat
function ScheduleStory({ categories: storyCategories = categories, events: storyEvents = events, height, highlightDate = defaultHighlightDate, plugins, timezoneID = localTimezoneID, view, viewDate: initialViewDate = defaultViewDate,}: { categories?: ReadonlyArray<ScheduleCategory>; events?: ScheduleEventSource; height?: ScheduleHeight; highlightDate?: Instant; plugins?: SchedulePlugin[]; timezoneID?: string; view: ScheduleView; viewDate?: Instant;}) { const [viewDate, setViewDate] = useState<Instant>(() => initialViewDate); const paginationPlugin = useSchedulePaginationPlugin({ onViewDateChange: setViewDate, }); return ( <Schedule categories={storyCategories} events={storyEvents} height={height} highlightDate={highlightDate} plugins={plugins ?? [paginationPlugin]} timezoneID={timezoneID} view={view} viewDate={viewDate} /> );}
() => { const viewDate = Temporal.PlainDate.from('2025-07-15').toZonedDateTime( 'UTC', ).epochMilliseconds; return ( <div className={automaticMonthRowsFillHeightContainer}> <ScheduleStory height="fill" highlightDate={viewDate} timezoneID="UTC" view={createScheduleMonthlyView()} viewDate={viewDate} /> </div> );}Show All Month Events
Section titled “Show All Month Events”August 2026
Sun
Mon
Tue
Wed
Thu
Fri
Sat
function ScheduleStory({ categories: storyCategories = categories, events: storyEvents = events, height, highlightDate = defaultHighlightDate, plugins, timezoneID = localTimezoneID, view, viewDate: initialViewDate = defaultViewDate,}: { categories?: ReadonlyArray<ScheduleCategory>; events?: ScheduleEventSource; height?: ScheduleHeight; highlightDate?: Instant; plugins?: SchedulePlugin[]; timezoneID?: string; view: ScheduleView; viewDate?: Instant;}) { const [viewDate, setViewDate] = useState<Instant>(() => initialViewDate); const paginationPlugin = useSchedulePaginationPlugin({ onViewDateChange: setViewDate, }); return ( <Schedule categories={storyCategories} events={storyEvents} height={height} highlightDate={highlightDate} plugins={plugins ?? [paginationPlugin]} timezoneID={timezoneID} view={view} viewDate={viewDate} /> );}
<ScheduleStory events={busyDayEvents} view={createScheduleMonthlyView({monthRowHeight: 'auto'})}/>Schedule
Section titled “Schedule”Read-only schedule shell for day, week, month, and list views.
| Prop | Type | Default | Description |
|---|---|---|---|
categories | ReadonlyArray<ScheduleCategory> | — | Category definitions used to style events by their category value. |
className | string | — | Additional CSS class names applied to the schedule root. |
data-testid | string | — | Test ID applied to the schedule root. |
events* | ScheduleEventSource | — | Static events or an async event loader. |
height | "fill" | "auto" | 'auto' | Height behavior. auto grows with the active view; fill occupies a finite-height parent and scrolls the view below the fixed toolbar. |
highlightDate | Instant | — | Instant highlighted as the current date. Defaults to mount time. |
plugins | ReadonlyArray<SchedulePlugin> | — | Header/rendering plugins. |
ref | Ref<HTMLDivElement> | — | Ref forwarded to the schedule root. |
style | CSSProperties | — | Inline styles applied to the schedule root. |
timezoneID | string | — | IANA timezone ID used for date math and rendering. |
view* | ScheduleView<Options> | — | View object returned by a createSchedule*View factory. |
viewDate* | Instant | — | Instant used to choose the rendered range. |
ScheduleEventPopoverContent
Section titled “ScheduleEventPopoverContent”Default Google-Calendar-style content for the event popover. Renders the event color, title, date/time, and category in a MetadataList with icon-only labels, plus optional `description` and `location` rows, an attendee response footer, and optional edit/delete actions — each shown only when the corresponding data or callback is present. A close button is always rendered. Pass this to the event popover plugin's `renderContent` to wire actions, e.g. `renderContent: (event, controls) => <ScheduleEventPopoverContent event={event} onClose={controls.close} onEdit={...} />`.
| Prop | Type | Default | Description |
|---|---|---|---|
event* | CalendarEvent<TAuxiliaryData> | — | The event to display. |
onClose* | () => void | — | Closes the popover. Wired to the close button. |
onDelete | (event: CalendarEvent<TAuxiliaryData>) => void | — | Called when the delete action is triggered. When omitted, no delete button is rendered. |
onEdit | (event: CalendarEvent<TAuxiliaryData>) => void | — | Called when the edit action is triggered. When omitted, no edit button is rendered. |
onRespond | ( event: CalendarEvent<TAuxiliaryData>, response: string | null, ) => void | — | Called when the attendee response (Going / Not Going / Maybe) changes. The response is null when the selection is cleared. |