Installation
CalendarKit offers two versions: Basic and Pro. Both are free and open source!
Basic (Free - Open Source)
Install directly from npm - no purchase needed! Full-featured calendar with modern UI and mobile support.
- ✓ Month, Week, Day views
- ✓ Event creation & editing
- ✓ Event overlap detection
- ✓ Custom event renderer
- ✓ Week start configuration
- ✓ Mobile swipe gestures
- ✓ Loading skeletons & empty states
- ✓ Calendar filtering
- ✓ Dark mode support
- ✓ Full TypeScript support
- ✓ MIT License
Pro (Premium - Open Source)
Install directly from npm! Professional features for production apps.
- ✓ Everything in Basic
- ✓ Drag & drop events
- ✓ Event resizing with 15-min snapping
- ✓ Agenda & Resource views
- ✓ Dark mode & i18n
- ✓ Timezone support
- ✓ Recurring events (RRULE)
- ✓ Event reminders & notifications
- ✓ ICS import/export
- ✓ Context menus (right-click)
- ✓ Mobile swipe gestures
- ✓ Skeleton loading & empty states
- ✓ Event attachments & guests
- ✓ MIT License
# Basic (Free - Open Source)
npm install calendarkit-basic
# or
yarn add calendarkit-basic
# or
pnpm add calendarkit-basic
# Pro (Premium - Open Source)
npm install calendarkit-pro
# or
yarn add calendarkit-pro
# or
pnpm add calendarkit-proBasic Usage
The BasicScheduler component provides essential calendar functionality with month, week, and day views.
import { BasicScheduler } from 'calendarkit-basic';
import { CalendarEvent, ViewType } from 'calendarkit-basic';
import { useState } from 'react';
export default function MyCalendar() {
const [events, setEvents] = useState<CalendarEvent[]>([]);
const [view, setView] = useState<ViewType>('week');
const [date, setDate] = useState(new Date());
return (
<BasicScheduler
events={events}
view={view}
onViewChange={setView}
date={date}
onDateChange={setDate}
onEventCreate={(event) => {
setEvents([...events, { ...event, id: Date.now().toString() }]);
}}
/>
);
}Pro UsagePro
The ProScheduler includes all Basic features plus drag & drop, agenda view, resource view, timezone support, dark mode, i18n, and recurring events.
import { Scheduler, CalendarEvent, ViewType, Resource } from 'calendarkit-pro';
import { useState } from 'react';
export default function MyCalendar() {
const [events, setEvents] = useState<CalendarEvent[]>([]);
const [view, setView] = useState<ViewType>('week');
const [date, setDate] = useState(new Date());
const [isDarkMode, setIsDarkMode] = useState(false);
return (
<Scheduler
events={events}
view={view}
onViewChange={setView}
date={date}
onDateChange={setDate}
isDarkMode={isDarkMode}
onThemeToggle={() => setIsDarkMode(!isDarkMode)}
onEventCreate={(event) => {
setEvents([...events, { ...event, id: Date.now().toString() }]);
}}
/>
);
}Events
Events are the core data structure in CalendarKit. Each event must have a unique ID, title, start, and end date.
interface CalendarEvent {
id: string; // Unique identifier
title: string; // Event title
start: Date; // Start date/time
end: Date; // End date/time
description?: string; // Optional description
color?: string; // Hex color (e.g., '#3b82f6')
allDay?: boolean; // Is all-day event
calendarId?: string; // Associated calendar ID
resourceId?: string; // For resource view (Pro only)
guests?: string[]; // Email addresses (Pro only)
attachments?: EventAttachment[]; // Files (Pro only)
recurrence?: { // Recurring rules (Pro only)
freq: 'DAILY' | 'WEEKLY' | 'MONTHLY' | 'YEARLY';
interval?: number;
count?: number; // Number of occurrences
until?: Date; // End date
};
}Required Fields
id- Unique identifier for the eventtitle- Display name of the eventstart- JavaScript Date object for start timeend- JavaScript Date object for end time
Calendars
Calendars allow users to organize and filter events by category. Each calendar has a color and can be toggled on/off.
const calendars = [
{ id: 'work', label: 'Work', color: '#3b82f6', active: true },
{ id: 'personal', label: 'Personal', color: '#10b981', active: true },
{ id: 'family', label: 'Family', color: '#8b5cf6', active: false },
];
<BasicScheduler
events={events}
calendars={calendars}
onCalendarToggle={(id, active) => {
setCalendars(cals =>
cals.map(c => c.id === id ? { ...c, active } : c)
);
}}
/>Event Handlers
CalendarKit provides callback functions for all user interactions. Use these to sync with your backend or state management.
<ProScheduler
events={events}
// Called when user clicks on an event
onEventClick={(event) => {
console.log('Event clicked:', event);
}}
// Called when user creates a new event
onEventCreate={(event) => {
setEvents([...events, { ...event, id: Date.now().toString() }]);
}}
// Called when user updates an existing event
onEventUpdate={(updatedEvent) => {
setEvents(events.map(e =>
e.id === updatedEvent.id ? updatedEvent : e
));
}}
// Called when user deletes an event
onEventDelete={(eventId) => {
setEvents(events.filter(e => e.id !== eventId));
}}
// Called when user drags an event to a new time (Pro only)
onEventDrop={(event, newStart, newEnd) => {
setEvents(events.map(e =>
e.id === event.id ? { ...e, start: newStart, end: newEnd } : e
));
}}
/>BasicScheduler Props
Complete reference of all props available in BasicScheduler.
// BasicScheduler Props
interface BasicSchedulerProps {
// Data
events?: CalendarEvent[];
calendars?: Calendar[];
// View Control
view?: 'month' | 'week' | 'day';
onViewChange?: (view: ViewType) => void;
date?: Date;
onDateChange?: (date: Date) => void;
// Week Start Configuration
weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6; // 0 = Sunday, 1 = Monday, etc.
// Event Handlers
onEventClick?: (event: CalendarEvent) => void;
onEventCreate?: (event: Partial<CalendarEvent>) => void;
onEventUpdate?: (event: CalendarEvent) => void;
onEventDelete?: (eventId: string) => void;
onCalendarToggle?: (calendarId: string, active: boolean) => void;
// Customization
theme?: CalendarTheme;
locale?: Locale;
className?: string;
readOnly?: boolean;
isLoading?: boolean;
// Custom Rendering
renderEventForm?: (props: EventFormProps) => React.ReactNode;
renderEvent?: (props: {
event: CalendarEvent;
view: ViewType;
onClick: () => void;
}) => React.ReactNode;
}| Prop | Type | Default | Description |
|---|---|---|---|
| events | CalendarEvent[] | [] | Array of events to display |
| view | 'month' | 'week' | 'day' | 'week' | Current calendar view |
| date | Date | new Date() | Currently focused date |
| calendars | Calendar[] | undefined | Calendar categories for filtering |
| locale | Locale | undefined | date-fns locale for date formatting |
| readOnly | boolean | false | Disable event creation/editing |
| isLoading | boolean | false | Show loading skeleton |
| weekStartsOn | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 0 | First day of week (0=Sunday, 1=Monday) |
| renderEvent | function | undefined | Custom event renderer component |
BasicScheduler Views
Month View
Traditional calendar grid showing all days in the current month. Events are displayed as colored bars. Respects weekStartsOn configuration.
Week View
7-day view with hourly grid. Smart event overlap detection displays overlapping events side-by-side. Virtualized for performance.
Day View
Single day view with detailed hourly breakdown. 15-minute time slots with event collision detection for overlapping events.
New in v1.0.0
- ✓ Event overlap detection with side-by-side display
- ✓ Configurable week start (Sunday through Saturday)
- ✓ Custom event renderer for complete control
- ✓ Event view modal with edit/delete actions
- ✓ Mobile swipe gestures for navigation
- ✓ Loading skeletons and empty states
Week Start Configuration
Configure which day the week starts on. Affects Week view, Month view, and Mini Calendar.
// Configure which day the week starts on
<BasicScheduler
events={events}
weekStartsOn={1} // 0 = Sunday (default), 1 = Monday, etc.
// Affects Week view, Month view, and Mini Calendar
/>
// Common configurations:
// weekStartsOn={0} // Sunday (US default)
// weekStartsOn={1} // Monday (EU/ISO standard)
// weekStartsOn={6} // Saturday (Middle East)| Value | Day | Common Usage |
|---|---|---|
| 0 | Sunday | US, Canada, Japan (default) |
| 1 | Monday | Europe, ISO standard |
| 6 | Saturday | Middle East |
Custom Event Renderer
Use the renderEvent prop for complete control over event appearance across all views.
// Custom event renderer for complete control over appearance
<BasicScheduler
events={events}
renderEvent={({ event, view, onClick }) => (
<div
onClick={onClick}
className="p-2 rounded cursor-pointer hover:opacity-80"
style={{ backgroundColor: event.color }}
>
<div className="font-semibold text-white truncate">
{event.title}
</div>
{view !== 'month' && (
<div className="text-xs text-white/80">
{format(event.start, 'h:mm a')} - {format(event.end, 'h:mm a')}
</div>
)}
</div>
)}
/>Render Props
event- The CalendarEvent object with all event dataview- Current view type ('month' | 'week' | 'day')onClick- Click handler to open event modal
Mobile Features
Built-in mobile support with swipe gestures, bottom sheet, and floating action buttons.
// Mobile features are built-in:
// - Swipe left/right to navigate dates
// - Mobile bottom sheet for calendar/filters
// - Floating action buttons (FAB)
// Swipe gestures work automatically on touch devices
<BasicScheduler
events={events}
view={view}
onViewChange={setView}
/>
// Mobile Bottom Sheet provides:
// - Mini calendar for date selection
// - Calendar filter toggles
// - View switcher (Month/Week/Day)Swipe Gestures
Swipe left/right to navigate between time periods. Works on all views with configurable threshold.
Mobile Bottom Sheet
Quick access to mini calendar, calendar filters, and view switcher. Opens via the calendar FAB.
Floating Action Buttons
Calendar/filter button and create event FAB. The create button respects the readOnly prop.
Loading States
Beautiful skeleton loading animations and empty state components for a polished UX.
import {
BasicScheduler,
CalendarSkeleton,
MonthViewSkeleton,
WeekViewSkeleton,
DayViewSkeleton,
EmptyState
} from 'calendarkit-basic';
// Use isLoading prop for built-in skeleton
<BasicScheduler
events={events}
isLoading={isLoadingEvents}
/>
// Or use skeleton components directly
{isLoading ? (
<CalendarSkeleton />
) : (
<BasicScheduler events={events} />
)}
// Empty state component
<EmptyState
title="No events scheduled"
description="Create your first event to get started"
actionLabel="Create Event"
onAction={() => setIsModalOpen(true)}
/>Skeleton Components
CalendarSkeleton, MonthViewSkeleton, WeekViewSkeleton, DayViewSkeleton - Animated shimmer effect placeholders.
Empty State
Customizable component with icon, title, description, and optional action button.
ProScheduler PropsPro
ProScheduler extends BasicScheduler with additional features. All Basic props are available plus:
// ProScheduler Props (includes all BasicScheduler props)
interface ProSchedulerProps extends BasicSchedulerProps {
// Additional Views
view?: 'month' | 'week' | 'day' | 'agenda' | 'resource';
resources?: Resource[];
// Drag & Drop
onEventDrop?: (event: CalendarEvent, start: Date, end: Date) => void;
onEventResize?: (event: CalendarEvent, start: Date, end: Date) => void;
// Timezone
timezone?: string;
onTimezoneChange?: (timezone: string) => void;
// Theme
isDarkMode?: boolean;
onThemeToggle?: () => void;
// i18n
language?: 'en' | 'fr';
onLanguageChange?: (lang: 'en' | 'fr') => void;
translations?: Partial<CalendarTranslations>;
// Pro Features
eventTypes?: EventType[];
hideViewSwitcher?: boolean;
}| Prop | Type | Description |
|---|---|---|
| timezone | string | IANA timezone (e.g., 'America/New_York') |
| isDarkMode | boolean | Enable dark theme |
| language | 'en' | 'fr' | UI language for built-in translations |
| translations | CalendarTranslations | Custom translation overrides |
| resources | Resource[] | Resources for resource view |
| onEventDrop | function | Callback when event is dragged |
| onEventResize | function | Callback when event is resized |
| hideViewSwitcher | boolean | Hide the view toggle buttons |
ProScheduler ViewsPro
All Basic Views
Month, Week, and Day views with drag & drop support.
Agenda View Pro
List view showing upcoming events in chronological order. Perfect for quick overview.
Resource View Pro
Display events by resource (rooms, people, equipment). Ideal for booking systems.
Drag & DropPro
Smoothly drag events to reschedule them. Works across Month, Week, Day, and Resource views.
// Drag & drop is built-in to ProScheduler
<ProScheduler
events={events}
// Called when an event is dragged to a new time
onEventDrop={(event, newStart, newEnd) => {
setEvents(events.map(e =>
e.id === event.id
? { ...e, start: newStart, end: newEnd }
: e
));
}}
// Optional: disable drag for specific scenarios
readOnly={false}
/>
// Drag features:
// - Smooth drag with snap-to-grid (15-min intervals)
// - Visual drag preview with event color
// - Works in Month, Week, Day, and Resource viewsFeatures
- ✓ Snap-to-grid (15-minute intervals)
- ✓ Visual drag preview with event color and shadow
- ✓ Works in all views including Resource view
- ✓ Respects readOnly prop
Event ResizingPro
Drag the bottom edge of events to resize them directly in the week and day views. Events snap to 15-minute intervals with visual feedback during resize.
// Event resizing is enabled by default in ProScheduler
// Users can drag the bottom edge of events to resize them
<Scheduler
events={events}
// Called when user resizes an event by dragging
onEventResize={(event, newStart, newEnd) => {
setEvents(events.map(e =>
e.id === event.id ? { ...e, start: newStart, end: newEnd } : e
));
}}
/>
// The ResizableEvent component handles:
// - 15-minute snap intervals for precise scheduling
// - Visual feedback during resize (cursor, preview)
// - Minimum duration constraintsFeatures
- ✓ Drag bottom edge to resize events
- ✓ 15-minute snap intervals
- ✓ Visual feedback during resize
- ✓ Works in Week and Day views
Timezone SupportPro
Display events in any timezone. Users can switch timezones on the fly.
<ProScheduler
events={events}
timezone="America/New_York" // IANA timezone
onTimezoneChange={(tz) => {
setTimezone(tz);
// Events will automatically adjust to new timezone
}}
/>
// Supported timezones include:
// - America/New_York
// - America/Los_Angeles
// - Europe/London
// - Europe/Paris
// - Asia/Tokyo
// - And all IANA timezone identifiersInternationalizationPro
Built-in support for English and French. Add custom translations for any language.
import { fr, de, es } from 'date-fns/locale';
// Custom translations
const customTranslations = {
today: 'Heute',
month: 'Monat',
week: 'Woche',
day: 'Tag',
createEvent: 'Ereignis erstellen',
editEvent: 'Ereignis bearbeiten',
delete: 'Löschen',
save: 'Speichern',
cancel: 'Abbrechen',
// ... more translations
};
<ProScheduler
events={events}
language="fr" // Built-in: 'en' | 'fr'
locale={fr} // date-fns locale for date formatting
translations={customTranslations} // Override specific strings
onLanguageChange={(lang) => setLanguage(lang)}
/>Recurring EventsPro
Create events that repeat daily, weekly, monthly, or yearly. Supports count-based and date-based end rules.
const recurringEvents = [
{
id: '1',
title: 'Daily Standup',
start: new Date(2025, 0, 6, 9, 0),
end: new Date(2025, 0, 6, 9, 30),
recurrence: {
freq: 'DAILY',
interval: 1, // Every 1 day
count: 30, // Repeat 30 times
},
},
{
id: '2',
title: 'Weekly Team Meeting',
start: new Date(2025, 0, 6, 14, 0),
end: new Date(2025, 0, 6, 15, 0),
recurrence: {
freq: 'WEEKLY',
interval: 1,
until: new Date(2025, 12, 31), // End date
},
},
{
id: '3',
title: 'Monthly Report',
start: new Date(2025, 0, 1, 10, 0),
end: new Date(2025, 0, 1, 11, 0),
recurrence: {
freq: 'MONTHLY',
interval: 1,
count: 12,
},
},
];Recurrence Options
freq- Frequency: DAILY, WEEKLY, MONTHLY, YEARLYinterval- Repeat every N periods (default: 1)count- Total number of occurrencesuntil- End date for recurrence
Resource ViewPro
Display events by resource - perfect for room booking, team scheduling, or equipment allocation.
const resources = [
{ id: 'room-a', label: 'Conference Room A', color: '#3b82f6' },
{ id: 'room-b', label: 'Conference Room B', color: '#10b981' },
{ id: 'john', label: 'John Doe', color: '#f59e0b', avatar: '/avatars/john.jpg' },
];
const events = [
{
id: '1',
title: 'Client Meeting',
start: new Date(2025, 0, 15, 10, 0),
end: new Date(2025, 0, 15, 11, 0),
resourceId: 'room-a', // Link event to resource
},
];
<ProScheduler
events={events}
resources={resources}
view="resource"
/>ICS Import/ExportPro
Import and export calendar events in the standard ICS format. Compatible with Google Calendar, Apple Calendar, Outlook, and more.
// ICS utilities are included in calendarkit-pro
// You can implement your own ICS handling like this:
// Export events to ICS file
const handleExport = () => {
const icsContent = generateICS(events, calendars);
const blob = new Blob([icsContent], { type: 'text/calendar' });
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = 'calendar.ics';
link.click();
};
// Import events from ICS file
const handleImport = async (file: File) => {
const text = await file.text();
const importedEvents = parseICS(text);
setEvents([...events, ...importedEvents]);
};
// Supports:
// - Recurring events (RRULE)
// - All-day events
// - Event attachments
// - Multiple calendarsSupported Features
- ✓ Full ICS generation and parsing
- ✓ Recurring events support
- ✓ All-day events
- ✓ Attachments support
- ✓ Import/Export buttons in Sidebar
Notification RemindersPro
Add reminder notifications to events with predefined intervals. Users can set multiple reminders per event.
// Events can have multiple reminders
interface EventReminder {
id: string;
minutes: number; // Minutes before event
type: 'notification' | 'email';
}
const event: CalendarEvent = {
id: '1',
title: 'Team Meeting',
start: new Date(2025, 0, 15, 14, 0),
end: new Date(2025, 0, 15, 15, 0),
reminders: [
{ id: 'r1', minutes: 15, type: 'notification' }, // 15 min before
{ id: 'r2', minutes: 60, type: 'email' }, // 1 hour before
],
};
// Built-in reminder options in EventModal:
// - 5 minutes before
// - 10 minutes before
// - 15 minutes before
// - 30 minutes before
// - 1 hour before
// - 1 day beforeReminder Options
- ✓ 5, 10, 15, 30 minutes before
- ✓ 1 hour before
- ✓ 1 day before
- ✓ Multiple reminders per event
Theming
Customize colors, fonts, and border radius. Both Basic and Pro support custom themes.
const customTheme = {
colors: {
primary: '#6366f1', // Primary accent color
secondary: '#ec4899', // Secondary color
background: '#ffffff', // Background color
foreground: '#0f172a', // Text color
border: '#e2e8f0', // Border color
muted: '#f1f5f9', // Muted backgrounds
accent: '#f1f5f9', // Accent backgrounds
},
fontFamily: 'Inter, sans-serif',
borderRadius: '0.75rem',
};
<ProScheduler
events={events}
theme={customTheme}
isDarkMode={isDarkMode}
onThemeToggle={() => setIsDarkMode(!isDarkMode)}
/>Custom Event Form
Replace the built-in event form with your own custom component. Works with both Basic and Pro schedulers.
<ProScheduler
events={events}
renderEventForm={({ isOpen, onClose, event, initialDate, onSave, onDelete }) => (
<MyCustomModal isOpen={isOpen} onClose={onClose}>
<MyEventForm
event={event}
initialDate={initialDate}
onSave={(data) => {
onSave(data);
onClose();
}}
onDelete={event?.id ? () => {
onDelete?.(event.id);
onClose();
} : undefined}
/>
</MyCustomModal>
)}
/>Render Props
isOpen- Whether the form should be visibleonClose- Function to close the formevent- Existing event (for edit mode) or nullinitialDate- Pre-filled date for new eventsonSave- Function to save the eventonDelete- Function to delete the event
Need help? Contact support
Back to home