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

NameTypeDefaultDescription
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
number4

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
stringWhatever your local timezone is

Timezone for date handling (e.g., "UTC", "America/New_York")

stickyViewHeader
booleantrue

Whether to stick the view header to the top

viewHeaderClassName
string''

Custom class name for the view header

headerComponent
ReactNodenull

Custom header component to render above the calendar

disableCellClick
booleanfalse

Disable cell click interactions

disableEventClick
booleanfalse

Disable event click interactions

disableDragAndDrop
booleanfalse

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

NameTypeDefaultDescription
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'
};