z-cal
A Temporal-native event calendar with a vanilla DOM API and React 19 bindings in one package.
Month, week, day, list, and resource views; drag, resize, select, recurring events, and custom event content.
Timed events reclaim unused space, with customizable details on hover or keyboard focus (eventTooltipContent). Click a day header to widen a crowded day while keeping the week visible. Enable scrollToFirstEvent to start at the earliest scheduled time, or swipeNavigation to swipe between periods.
Opt in to keyboardNavigation for arrow-key access to every cell and slot, with Google-style keyboardShortcuts and screen-reader announcements.
Set businessHours to shade closed time, and keep drags, resizes, and selections inside it or off other events with 'businessHours' constraints and eventOverlap.
Docs and live demos · npm · Documentation · Agent guide
Install
For React apps, also install React 19 if it is not already installed:
Import the stylesheet once. Import z-cal/polyfill before using the calendar unless all your
runtimes already provide Temporal. React is an optional peer dependency: vanilla users do not
need it. The package is ESM; React bindings live at z-cal/react, not a separate npm package.
Solid and Svelte adapters are not yet available.
React quickstart
In a client-rendered React application:
This renders the sample week with a draggable event. To show today's week, omit date.
To create events from a selection, enable selectable and handle select in your application.
The library emits a range; your application supplies the form and persistence.
Vanilla quickstart
Add <div id="calendar"></div> to your page, then run this module after the element exists:
Find the right guide
Important behavior
Replacing FullCalendar? Read the migration checklist for duration units, callback differences, and current API gaps.
- Supply the plugin that provides your
view;Interactionenables selection and event editing. keyboardShortcutslistens on the calendar root by default; pass{ target: document }for page-wide keys. They never fire in text fields or with a modifier held.- Dates returned by callbacks are Temporal values. All-day ranges have an exclusive end.
updateEventreplaces an event; supply its complete input, includingstart.Recurrenceexpandsrecurrencerules (RRULE text or an object) into occurrences; each callback event carriesoccurrence, and theeditRecurringEventhelper produces the series inputs for "this", "this and following", and "all".- Replacing
eventsor refetching sources replaces the corresponding loaded data. Persist edits in your application. Keep unchanged React arrays/objects stable across renders. - Drag/resize commits are canceled if the event was replaced during the gesture. A delayed
revert()leaves newer edits intact. See editing and persistence. responsiveWeekadjuststimeGridWeekand its derived views to their container width.- Define
heightto fill a container vertically.height="100%"needs a parent with a defined height.
License
MIT.