The React Calendar displays time vertically, with days or resources as columns. Use a week view to follow appointments across dates, or a resource view to compare several schedules on the same day. Users can select a time range, move an appointment to another column, or resize its duration.
Choose DayPilot Lite, the open-source edition under the Apache License 2.0, or DayPilot Pro, the commercial edition with additional scheduling features. Both provide React components, TypeScript definitions, day/week views, resource columns, and custom event rendering with JSX.
Try the day/week/month calendar · Try the resource calendar · Configure a calendar in UI Builder

React Calendar Features
DayPilot Lite and Pro
Day, week, and custom day views. Show one day, a work week, a full week, or a chosen number of days. Add previous/next buttons or a React date picker to move through the schedule. A month overview uses the separate React monthly calendar; the combined-view tutorial below shows how to connect them.
Resources as columns. Use a resource calendar to compare the daily schedules of people, rooms, or equipment side by side. Each event's
resourcematches a column ID. Changing the column name keeps that association; moving an event between resource columns changes its assignment.Event creation and editing. Handle a time-range selection to open an editor or create an event. Support drag-and-drop moving and resizing, and display a delete icon. The callbacks let your React application update its state and save the changes to your backend.
Custom event content. Use colors, labels, icons, and event actions to make appointments easy to recognize. Render JSX inside events, including React components with their own click handlers, and use CSS themes to match the calendar to your application.
Working hours and local date formats. Set business hours, time-slot duration, and the first day of the week. Choose a locale for date and time formatting, and supply your application's own translated labels.
Additional DayPilot Pro Features
Grouped resource schedules. Organize rooms by location or staff by team using a column-header hierarchy. You can also group resource columns under dates when users need to plan across several days.
Wide calendars. Keep resource columns at a fixed width and use horizontal scrolling to reach more resources. This keeps a busy schedule readable without squeezing every column into the available window. You can enable progressive event rendering for fixed-width calendars to limit rendering work around the viewport.
Overnight and all-day scheduling. Configure overnight schedules for shifts that cross midnight. Display all-day events above the time grid when an item belongs to a day rather than a specific hour.
Touch interaction. Support scheduling gestures on touch devices. Combine touch support with an application layout and controls that suit the available screen space.
Export. Export a JPEG, PNG, or SVG image, embed an image in a PDF document, or create an Excel spreadsheet. The export guides describe format-specific libraries and limits.
See the feature matrix for the full edition comparison. For a horizontal timeline with resources as rows, use the React Scheduler.
Change the Resource Layout Using the Same Event Data

The grouped-resource example switches between five columns, fifty fixed-width columns, days containing resources, resources containing days, and resource groups. The grouped view shown here puts related resources under a shared header. Switch to resources/days to put dates under each resource: these child columns repeat the resource ID and specify their own date. The event's resource and date identify the matching column, so the same records fit several arrangements. Try the layout buttons (Pro).
The Lite resource example demonstrates a different choice: its group selector replaces the visible columns with Locations, People, or Tools. Click a header's edit icon to rename a resource in a dialog. The header customization hook supplies the icon, while the React application updates the column data. Try group selection and header editing.
Put React Controls Inside an Appointment
The JSX event-content example puts two information icons in the same event: one is an active area and the other is part of the JSX supplied through onBeforeEventDomAdd. Both open the event's details. Use an active area to position an action relative to the event box, or JSX to compose event content from React elements. The hook receives the current event as args.e and accepts the rendered element as args.element. Compare the two icons (Lite).
React Calendar Demos and Tutorials
These tutorials include downloadable projects and explain how each example works. The edition is shown for each tutorial so you can explore examples that match your package.
React Views and Navigation
React Weekly Calendar · Live demo (Lite)
Start with a weekly calendar, a date picker, drag-and-drop editing, and custom event colors.React Resource Calendar with Editable Columns · Live demo (Lite)
Display resources as columns, switch between locations, people, or tools, and edit column names.React Calendar with Day/Week/Month Views · Live demo (Lite)
Combine Calendar, Month, and Navigator components, sharing event data between the daily, weekly, and monthly views.React Calendar with a Popup Date Picker · Live demo (Lite)
Open a compact date picker from a button and use the selected date to update the calendar.
React Content and Advanced Views
Rendering JSX in Calendar Events · Live demo (Lite)
Add custom React content inside event boxes, with icons that open event details. Compare JSX with built-in active areas.React Resource Calendar with Grouped Columns · Live demo (Pro)
Switch between resource/date hierarchies and fixed-width columns using React state and function components.React Calendar with a Vertical Timeline · Live demo (Pro)
Configure the Pro Calendar with dates on the vertical axis and resources as columns, for a longer planning range.React Yearly Scheduling Calendar · Live demo (Pro)
Display a year with months as columns and days on the vertical axis, with weekday labels and events that can span month boundaries.
Next.js Calendars
Next.js Weekly Calendar · Live demo (Lite)
Add a weekly event calendar to a Next.js application using the browser-side component setup.Next.js Resource-Scheduling Calendar · Live demo (Lite)
Build a resource calendar with editable headers and application callbacks that control event creation and moving.Next.js Calendar with Day/Week/Month Views · Live demo (Lite)
Connect daily, weekly, and monthly components in a Next.js application with a shared date picker and event data.
Browse more React Calendar and Scheduler tutorials.
Configure a React Calendar Visually
The Calendar UI Builder lets you adjust calendar options in a live preview. Select a React target and the edition you want to use, then download a starter project with your configuration. Continue editing the options in your React code.
Installation
DayPilot Lite
Install @daypilot/daypilot-lite-react from npm:
npm install @daypilot/daypilot-lite-react
DayPilot Pro
At npm.daypilot.org, select React and copy the installation command for daypilot-pro-react. Licensed customers can obtain their package URL in the customer area.
The examples use JavaScript/JSX and function components with React 18 or later.
Display a Weekly Appointment Calendar
Start with a Monday-first week and one two-hour meeting.
Calendar.jsx
import {useState} from 'react';
import {DayPilot, DayPilotCalendar} from '@daypilot/daypilot-lite-react';
export default function Calendar() {
const [events] = useState([
{id: 'meeting', text: 'Meeting',
start: '2026-10-05T10:00:00', end: '2026-10-05T12:00:00'}
]);
return <DayPilotCalendar
startDate="2026-10-05"
viewType="Week"
weekStarts={1}
events={events}
/>;
}
viewType: "Week" displays a week containing startDate. weekStarts: 1 makes Monday the first column. Events use a unique id, display text, and start/end date-times. The meeting ends at 12:00; event ends are exclusive.
The examples use Lite. For Pro, change the package import to daypilot-pro-react.
See event loading for data formats and loading options.
Navigate and Load Appointments
Previous and Next move by one week. Request appointments for that week, then replace the bound event array with the JSON array returned by your backend.
CalendarLoading.jsx
import {useState, useEffect} from 'react';
import {DayPilot, DayPilotCalendar} from '@daypilot/daypilot-lite-react';
export default function Calendar() {
const [startDate, setStartDate] = useState(new DayPilot.Date('2026-10-05'));
const [events, setEvents] = useState([]);
useEffect(() => {
let active = true;
const start = startDate;
const end = start.addDays(7);
const url = `/api/events?start=${start}&end=${end}`;
async function load() {
try {
const {data} = await DayPilot.Http.get(url);
if (!active) { return; }
setEvents(data);
} catch {
if (active) { await DayPilot.Modal.alert('Could not load data.'); }
}
}
load();
return () => { active = false; };
}, [startDate]);
function navigate(offset) {
setStartDate(date => date.addDays(offset * 7));
}
return <>
<button onClick={() => navigate(-1)}>Previous week</button>
<button onClick={() => navigate(1)}>Next week</button>
<DayPilotCalendar
startDate={startDate}
viewType="Week"
weekStarts={1}
events={events}
/>
</>;
}
The /api/events URL represents your own backend. Return items that overlap the requested range: item start is before the requested end, and item end is after the requested start. Failed requests display a DayPilot dialog.
The effect cleanup prevents an older response from replacing data after another navigation action.
Create Appointments by Selecting Time
This complete variation of the first example handles time range selection. The selection supplies the dates; the dialog supplies the name.
CalendarCreation.jsx
import {useState} from 'react';
import {DayPilot, DayPilotCalendar} from '@daypilot/daypilot-lite-react';
export default function Calendar() {
const [events] = useState([
{id: 'meeting', text: 'Meeting',
start: '2026-10-05T10:00:00', end: '2026-10-05T12:00:00'}
]);
return <DayPilotCalendar
startDate="2026-10-05"
viewType="Week"
weekStarts={1}
events={events}
onTimeRangeSelected={async args => {
const modal = await DayPilot.Modal.prompt('Appointment name:', 'New appointment');
args.control.clearSelection();
if (modal.canceled) { return; }
args.control.events.add({
id: DayPilot.guid(), text: modal.result,
start: args.start, end: args.end
});
}}
/>;
}
Canceling the dialog leaves the data unchanged. events.add() inserts the new event locally. In an application with a backend, create the record with a POST request and use the returned ID before adding it to the view.
Move, Resize and Save Events
Moving changes the event position; resizing changes its duration. Both work in the first example without extra configuration. The component updates the display and the supplied data object automatically.
Use the callbacks after the edit to persist the result. This example sends the changed record to the backend; it does not reload the collection after each drag.
CalendarSaving.jsx
import {useState} from 'react';
import {DayPilot, DayPilotCalendar} from '@daypilot/daypilot-lite-react';
export default function Calendar() {
const [events] = useState([
{id: 'meeting', text: 'Meeting',
start: '2026-10-05T10:00:00', end: '2026-10-05T12:00:00'}
]);
async function saveEvent(data) {
try {
await DayPilot.Http.put(`/api/events/${data.id}`, data);
} catch {
await DayPilot.Modal.alert('The change could not be saved.');
}
}
return <DayPilotCalendar
startDate="2026-10-05"
viewType="Week"
weekStarts={1}
events={events}
onEventMoved={args => saveEvent(args.e.data)}
onEventResized={args => saveEvent(args.e.data)}
/>;
}
The /api/events/{id} endpoint accepts the updated JSON record. A failed save is reported while the local edit remains visible; add retry or rollback behavior to suit your application. To disable an interaction, set eventMoveHandling or eventResizeHandling to "Disabled".
Handle an Event Click
To display the clicked item’s name, add this prop to the existing component:
onEventClick={args => DayPilot.Modal.alert(DayPilot.Util.escapeHtml(args.e.text()))}
DayPilot.Modal.alert() accepts HTML. escapeHtml() displays the item’s name as plain text.
Render Custom React Content
This independent variation of the first example adds JSX to the event through onBeforeEventDomAdd.
CalendarContent.jsx
import {useState} from 'react';
import {DayPilot, DayPilotCalendar} from '@daypilot/daypilot-lite-react';
export default function Calendar() {
const [events] = useState([
{id: 'meeting', text: 'Meeting',
start: '2026-10-05T10:00:00', end: '2026-10-05T12:00:00'}
]);
return <DayPilotCalendar
startDate="2026-10-05"
viewType="Week"
weekStarts={1}
events={events}
onBeforeEventDomAdd={args => {
args.element = <strong>{args.e.text()}</strong>;
}}
/>;
}
Access the Calendar API
Use the event collection API to find and rename the meeting. The wrapper reference, button and handler are shown together.
CalendarApi.jsx
import {useState} from 'react';
import {DayPilot, DayPilotCalendar} from '@daypilot/daypilot-lite-react';
export default function Calendar() {
const [calendar, setCalendar] = useState(null);
const [events] = useState([
{id: 'meeting', text: 'Meeting',
start: '2026-10-05T10:00:00', end: '2026-10-05T12:00:00'}
]);
async function renameEvent() {
const control = calendar;
const event = control.events.find('meeting');
const modal = await DayPilot.Modal.prompt('Event name:', event.text());
if (modal.canceled) { return; }
event.text(modal.result);
control.events.update(event);
}
return <>
<button disabled={!calendar} onClick={renameEvent}>Rename meeting</button>
<DayPilotCalendar
startDate="2026-10-05"
viewType="Week"
weekStarts={1}
events={events}
controlRef={setCalendar}
/>
</>;
}
React receives the underlying control through controlRef. The wrapper creates and disposes it. See the DayPilot.Calendar API for methods, properties and callbacks.
Use Next.js
Place the introductory component in Calendar.jsx and add 'use client'; at the top. Create a client wrapper that loads it with server rendering disabled:
CalendarClient.jsx
'use client';
import dynamic from 'next/dynamic';
const Calendar = dynamic(() => import('./Calendar'), {ssr: false});
export default function CalendarClient() {
return <Calendar />;
}
Import CalendarClient in your page and render <CalendarClient />. The Next.js client wrapper keeps the DayPilot component in the browser. The tutorials above provide complete project setups.
Availability
Availability of this feature in DayPilot editions:
| Product | Lite | Pro |
|---|---|---|
| DayPilot for JavaScript | ||
| DayPilot for ASP.NET WebForms | ||
| DayPilot for ASP.NET MVC | ||
| DayPilot for Java |
DayPilot