Calendar
A comprehensive React calendar component with month, week, day, and year views, plus powerful event lifecycle callbacks.
Basic Usage
The Calendar component is the main component for displaying calendar views. It supports various props for customization and event handling. Events should follow the CalendarEvent interface.
import { IlamyCalendar } from '@ilamy/calendar';
const events = [
{
id: '1',
title: 'Team Meeting',
start: new Date('2024-01-15T10:00:00'),
end: new Date('2024-01-15T11:00:00'),
description: 'Weekly team sync',
backgroundColor: '#3b82f6'
color: 'black'
},
{
id: '2',
title: 'Project Deadline',
start: new Date('2024-01-20T23:59:59'),
end: new Date('2024-01-20T23:59:59'),
allDay: true,
backgroundColor: '#ef4444'
color: 'black'
}
];
function MyCalendar() {
return (
<IlamyCalendar events={events} />
);
}
Props
Basic Props
Name | Type | Default | Description |
---|---|---|---|
events | CalendarEvent[] | [] | Array of events to display in the calendar |
initialView | 'month' | 'week' | 'day' | 'year' | 'month' | Sets the initial view when the calendar loads |
firstDayOfWeek | 'sunday' | 'monday' | 'tuesday' | 'wednesday' | 'thursday' | 'friday' | 'saturday' | 'sunday' | The first day of the week to display |
dayMaxEvents | number | 4 | Maximum number of events to display in a day cell |
renderEvent | (event: CalendarEvent) => ReactNode | — | Custom function to render individual events |
locale | string | 'en' | Locale for date formatting (e.g., "en", "fr", "de") |
timezone | string | Whatever your local timezone is | Timezone for date handling (e.g., "UTC", "America/New_York") |
stickyViewHeader | boolean | true | Whether to stick the view header to the top |
viewHeaderClassName | string | '' | Custom class name for the view header |
headerComponent | ReactNode | null | Custom header component to render above the calendar |
disableCellClick | boolean | false | Disable cell click interactions |
disableEventClick | boolean | false | Disable event click interactions |
disableDragAndDrop | boolean | false | Disable drag-and-drop functionality for events |
translations | Translations | — | Translations object for internationalization. If both translations and translator are provided, translator takes priority. |
translator | TranslatorFunction | — | Translator function for internationalization. Takes priority over translations object if both are provided. |
Event Handlers
Name | Type | Default | Description |
---|---|---|---|
onEventClick | (event: CalendarEvent) => void | — | Called when an event is clicked |
onCellClick | (date: Date) => void | — | Called when a date cell is clicked |
onViewChange | (view: 'month' | 'week' | 'day' | 'year') => void | — | Called when the calendar view changes |
onEventAdd | (event: CalendarEvent) => void | — | Called when a new event is created |
onEventUpdate | (event: CalendarEvent) => void | — | Called when an existing event is updated |
onEventDelete | (event: CalendarEvent) => void | — | Called when an event is deleted |
onDateChange | (date: dayjs.Dayjs) => void | — | Called when the calendar date changes |
Examples
With Event Handlers
import { IlamyCalendar } from '@ilamy/calendar';
function MyCalendar() {
const handleEventClick = (event) => {
console.log('Event clicked:', event);
// Open event details modal, navigate to event page, etc.
};
const handleDateClick = (date) => {
console.log('Date clicked:', date);
// Create new event, switch to day view, etc.
};
const handleViewChange = (view) => {
console.log('View changed to:', view);
// Update URL, track analytics, etc.
};
return (
<IlamyCalendar
events={events}
firstDayOfWeek="monday"
onEventClick={handleEventClick}
onCellClick={handleDateClick}
onViewChange={handleViewChange}
/>
);
}
Internationalization
The calendar supports comprehensive internationalization including locale-based formatting, custom translations, and translator functions. For detailed documentation and examples, see the Internationalization guide.
Custom Event Rendering
import { IlamyCalendar } from '@ilamy/calendar';
function CustomCalendar() {
const renderEvent = (event) => (
<div className="px-2 py-1 rounded bg-blue-100 text-blue-800">
<div className="font-semibold">{event.title}</div>
<div className="text-xs">{event.description}</div>
</div>
);
return (
<IlamyCalendar
events={events}
renderEvent={renderEvent}
onEventClick={(event) => alert(`Clicked: ${event.title}`)}
onCellClick={(date) => console.log('Selected date:', date)}
/>
);
}
Initial View and Event Lifecycle
import { IlamyCalendar } from '@ilamy/calendar';
import { useState } from 'react';
function AdvancedCalendar() {
const [events, setEvents] = useState([]);
const handleEventAdd = (event) => {
console.log('New event added:', event);
setEvents(prev => [...prev, event]);
// Save to your backend API
};
const handleEventUpdate = (updatedEvent) => {
console.log('Event updated:', updatedEvent);
setEvents(prev =>
prev.map(event =>
event.id === updatedEvent.id ? updatedEvent : event
)
);
// Update in your backend API
};
const handleEventDelete = (deletedEvent) => {
console.log('Event deleted:', deletedEvent);
setEvents(prev =>
prev.filter(event => event.id !== deletedEvent.id)
);
// Delete from your backend API
};
const handleDateChange = (date) => {
console.log('Date changed to:', date.format('YYYY-MM-DD'));
// Load events for the new date range
// fetchEventsForDate(date);
};
return (
<IlamyCalendar
events={events}
initialView="week" // Start with week view
onEventAdd={handleEventAdd}
onEventUpdate={handleEventUpdate}
onEventDelete={handleEventDelete}
onDateChange={handleDateChange}
onEventClick={(event) => console.log('Event clicked:', event)}
onCellClick={(date) => console.log('Cell clicked:', date)}
/>
);
}
View Options
The calendar supports multiple view modes that you can set using the
initialView
prop.
Month View
Traditional monthly calendar showing the entire month at a glance.
initialView="month"
Week View
Weekly view showing 7 days with detailed time slots.
initialView="week"
Day View
Single day view with hourly time slots for detailed scheduling.
initialView="day"
Year View
Annual overview showing all 12 months for long-term planning.
initialView="year"
// Month view (default)
<IlamyCalendar initialView="month" events={events} />
// Week view for detailed scheduling
<IlamyCalendar initialView="week" events={events} />
// Day view for hourly planning
<IlamyCalendar initialView="day" events={events} />
// Year view for long-term overview
<IlamyCalendar initialView="year" events={events} />
Event Lifecycle Callbacks
Handle event creation, updates, and deletion with powerful callback functions. These callbacks are essential for maintaining your event data and integrating with backend APIs.
Event Management Callbacks
onEventAdd
Triggered when a user creates a new event through the calendar interface.
(event: CalendarEvent) => void
onEventUpdate
Called when an existing event is modified (e.g., dragged, resized, or edited).
(event: CalendarEvent) => void
onEventDelete
Invoked when a user deletes an event from the calendar.
(event: CalendarEvent) => void
onDateChange
Fired when the user navigates to a different date or time period.
(date: dayjs.Dayjs) => void
Complete Integration Example
import { IlamyCalendar } from '@ilamy/calendar';
import { useState } from 'react';
function CalendarWithAPI() {
const [events, setEvents] = useState([]);
const [loading, setLoading] = useState(false);
// Handle new event creation
const handleEventAdd = async (event) => {
setLoading(true);
try {
// Save to backend
const response = await fetch('/api/events', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(event)
});
if (response.ok) {
const savedEvent = await response.json();
setEvents(prev => [...prev, savedEvent]);
console.log('Event created successfully:', savedEvent);
}
} catch (error) {
console.error('Failed to create event:', error);
} finally {
setLoading(false);
}
};
// Handle event updates
const handleEventUpdate = async (updatedEvent) => {
setLoading(true);
try {
const response = await fetch('/api/events/' + updatedEvent.id, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(updatedEvent)
});
if (response.ok) {
setEvents(prev =>
prev.map(event =>
event.id === updatedEvent.id ? updatedEvent : event
)
);
console.log('Event updated successfully:', updatedEvent);
}
} catch (error) {
console.error('Failed to update event:', error);
} finally {
setLoading(false);
}
};
// Handle event deletion
const handleEventDelete = async (deletedEvent) => {
setLoading(true);
try {
const response = await fetch('/api/events/' + deletedEvent.id, {
method: 'DELETE'
});
if (response.ok) {
setEvents(prev =>
prev.filter(event => event.id !== deletedEvent.id)
);
console.log('Event deleted successfully:', deletedEvent);
}
} catch (error) {
console.error('Failed to delete event:', error);
} finally {
setLoading(false);
}
};
// Handle date navigation
const handleDateChange = async (date) => {
console.log('Navigating to:', date.format('YYYY-MM-DD'));
// Optionally load events for the new date range
const monthStart = date.startOf('month');
const monthEnd = date.endOf('month');
try {
const response = await fetch(
'/api/events?start=' + monthStart.toISOString() +
'&end=' + monthEnd.toISOString()
);
if (response.ok) {
const monthEvents = await response.json();
setEvents(monthEvents);
}
} catch (error) {
console.error('Failed to load events for date:', error);
}
};
return (
<div className="relative">
{loading && (
<div className="absolute inset-0 bg-white/50 flex items-center justify-center z-10">
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600"></div>
</div>
)}
<IlamyCalendar
events={events}
initialView="month"
onEventAdd={handleEventAdd}
onEventUpdate={handleEventUpdate}
onEventDelete={handleEventDelete}
onDateChange={handleDateChange}
onEventClick={(event) => {
// Navigate to event details or open modal
console.log('Event clicked:', event);
}}
/>
</div>
);
}
Types
CalendarEvent Interface
The main event object used throughout the calendar. All events passed to the calendar should conform to this interface.
interface CalendarEvent {
id: string; // Unique identifier for the event
title: string; // Display title of the event
start: Date; // Start date and time
end: Date; // End date and time
description?: string; // Optional description text
color?: string; // Optional text color (hex, rgb, named colors, class names)
backgroundColor?: string; // Optional background color (hex, rgb, named colors, class names)
allDay?: boolean; // Whether this is an all-day event
data?: Record<string, any>; // Optional custom data for additional properties
}
Event Properties Explained
Required Properties
-
id
- Must be unique across all events. Used for drag-and-drop and event updates. -
title
- The text displayed on the event in the calendar. -
start
- JavaScript Date object representing when the event begins. -
end
- JavaScript Date object representing when the event ends.
Optional Properties
-
description
- Additional text shown in tooltips or custom event renderers. -
color
- Background color for the event. Supports hex (#ff0000), rgb(255,0,0), or named colors (red). -
allDay
- When true, the event spans the entire day and ignores time components.
Example Event Objects
// Regular timed event
const meeting = {
id: 'meeting-1',
title: 'Team Standup',
start: new Date('2024-01-15T09:00:00'),
end: new Date('2024-01-15T09:30:00'),
description: 'Daily team sync meeting',
color: '#3b82f6'
};
// All-day event
const holiday = {
id: 'holiday-1',
title: 'National Holiday',
start: new Date('2024-01-01'),
end: new Date('2024-01-01'),
allDay: true,
color: '#ef4444'
};
// Multi-day event
const conference = {
id: 'conf-1',
title: 'Tech Conference',
start: new Date('2024-01-20T08:00:00'),
end: new Date('2024-01-22T18:00:00'),
description: 'Annual technology conference',
color: '#10b981'
};