Resource Calendar
A powerful calendar component for visualizing and managing events across multiple resources like rooms, equipment, or team members.
Overview
The Resource Calendar extends the standard calendar with resource-based event organization. Events are displayed in horizontal rows where each row represents a resource (person, room, equipment, etc.). It supports all standard calendar features including drag-and-drop, recurring events, and internationalization.
Try it out: Visit the interactive demo and toggle to "Resource Calendar" mode to see it in action!
Basic Usage
import { IlamyResourceCalendar } from '@ilamy/calendar';
import type { Resource, ResourceCalendarEvent } from '@ilamy/calendar';
import dayjs from 'dayjs';
const resources: Resource[] = [
{
id: 'room-a',
title: 'Conference Room A',
color: '#3B82F6',
backgroundColor: '#EFF6FF',
},
{
id: 'room-b',
title: 'Conference Room B',
color: '#EF4444',
backgroundColor: '#FEF2F2',
},
];
const events: ResourceCalendarEvent[] = [
{
id: 'event-1',
title: 'Team Meeting',
start: dayjs('2025-08-04T09:00:00.000Z'),
end: dayjs('2025-08-04T10:00:00.000Z'),
uid: '[email protected]',
resourceId: 'room-a', // Assigned to Room A
},
];
function App() {
return (
<IlamyResourceCalendar
resources={resources}
events={events}
firstDayOfWeek="sunday"
initialView="week"
/>
);
} Note: For sticky headers to work properly, the calendar's container must have a fixed height (e.g., height: 600px).
Resource Interface
Resources represent the entities across which events are organized.
interface Resource {
// Unique identifier for the resource
id: string | number;
// Display title of the resource
title: string;
// Color for resource text (hex, rgb, or CSS class)
color?: string;
// Background color for resource (hex, rgb, or CSS class)
backgroundColor?: string;
// Optional position for resource display order
position?: number;
}Resource Color System
const resources: Resource[] = [
{
id: 'designer',
title: 'Design Team',
color: '#8B5CF6', // Purple text
backgroundColor: '#F5F3FF', // Light purple background
},
{
id: 'engineer',
title: 'Engineering Team',
color: '#10B981', // Green text
backgroundColor: '#ECFDF5', // Light green background
},
];Resource Calendar Events
Resource calendar events extend the standard CalendarEvent interface with resource assignment fields.
interface ResourceCalendarEvent extends CalendarEvent {
// Single resource assignment
resourceId?: string | number;
// Multiple resource assignment (cross-resource events)
resourceIds?: (string | number)[];
}Single Resource Events
const event: ResourceCalendarEvent = {
id: 'meeting-1',
title: 'Team Standup',
start: dayjs('2025-08-04T10:00:00.000Z'),
end: dayjs('2025-08-04T10:30:00.000Z'),
uid: '[email protected]',
resourceId: 'room-a', // Assigned to one resource
};Cross-Resource Events
Events that span multiple resources using the resourceIds array:
const event: ResourceCalendarEvent = {
id: 'all-hands',
title: 'All Hands Meeting',
start: dayjs('2025-08-04T14:00:00.000Z'),
end: dayjs('2025-08-04T15:00:00.000Z'),
uid: '[email protected]',
resourceIds: ['room-a', 'room-b', 'room-c'], // Spans multiple resources
color: '#8B5CF6',
};Props
The IlamyResourceCalendar component extends all props from IlamyCalendar with resource-specific additions.
Resource-Specific Props
| Name | Type | Default | Description |
|---|---|---|---|
resources | Resource[] | [] | Array of resources to display |
events | ResourceCalendarEvent[] | [] | Array of events with resource assignments |
renderResource | (resource: Resource) => ReactNode | — | Custom function to render resource headers |
Examples
Room Booking System
import { IlamyResourceCalendar } from '@ilamy/calendar';
import { useState } from 'react';
import dayjs from 'dayjs';
const RoomBookingCalendar = () => {
const [events, setEvents] = useState<ResourceCalendarEvent[]>([]);
const rooms: Resource[] = [
{
id: 'conf-a',
title: 'Conference Room A (10 people)',
color: '#3B82F6',
backgroundColor: '#EFF6FF',
},
{
id: 'conf-b',
title: 'Conference Room B (20 people)',
color: '#EF4444',
backgroundColor: '#FEF2F2',
},
{
id: 'board-room',
title: 'Board Room (8 people)',
color: '#8B5CF6',
backgroundColor: '#F5F3FF',
},
];
const handleCellClick = (
start: dayjs.Dayjs,
end: dayjs.Dayjs,
resourceId?: string | number
) => {
if (!resourceId) return;
const newEvent: ResourceCalendarEvent = {
id: `booking-${Date.now()}`,
title: 'New Booking',
start,
end,
uid: `booking-${Date.now()}@company.com`,
resourceId,
color: '#10B981',
};
setEvents((prev) => [...prev, newEvent]);
};
const handleEventUpdate = (event: ResourceCalendarEvent) => {
setEvents((prev) =>
prev.map((e) => (e.id === event.id ? event : e))
);
};
return (
<IlamyResourceCalendar
resources={rooms}
events={events}
initialView="week"
onCellClick={handleCellClick}
onEventUpdate={handleEventUpdate}
firstDayOfWeek="monday"
/>
);
};Custom Resource Rendering
Customize how resources are displayed using the renderResource prop:
import { Calendar, MapPin, Users } from 'lucide-react';
const IconResourceRenderer = (resource: Resource) => {
const getResourceIcon = (resourceId: string) => {
if (resourceId.includes('room')) return <MapPin className="h-4 w-4" />;
if (resourceId.includes('team')) return <Users className="h-4 w-4" />;
return <Calendar className="h-4 w-4" />;
};
return (
<div className="flex items-center gap-2 p-2">
<div style={{ color: resource.color }}>
{getResourceIcon(resource.id)}
</div>
<div className="flex flex-col">
<span className="font-medium">{resource.title}</span>
<span className="text-xs" style={{ color: resource.color }}>
Available
</span>
</div>
</div>
);
};
function App() {
return (
<IlamyResourceCalendar
resources={resources}
events={events}
renderResource={IconResourceRenderer}
/>
);
}Views
The Resource Calendar supports three views, each displaying resources in horizontal rows.
Month View
Timeline view with resources as rows and days as columns. Compact event display with scroll for all resources.
initialView="month" Week View
Detailed 7-day timeline with hourly time slots. Perfect for precise scheduling with drag-and-drop between resources.
initialView="week" Day View
Focused single-day view with maximum detail. Full hourly breakdown across all resources.
initialView="day" 🚧 Coming Soon: Custom Duration Views
Custom duration views (e.g., 3-day, 2-week, 4-week views) for the resource calendar are currently in development and will be available in a future release. Stay tuned for updates!
Best Practices
Resource Organization
- ✓ Use meaningful resource IDs (e.g., 'room-a', 'john-doe')
- ✓ Set position property to control display order
- ✓ Group related resources by type
- ✓ Include capacity info in resource titles when relevant
Event Assignment
- ✓ Use resourceId for single resource events (simpler and more performant)
- ✓ Use resourceIds array only when event truly spans multiple resources
- ✓ Validate resource IDs exist in resources array
- ✓ Handle conflicts and validate resource availability before booking
Performance
- ✓ Memoize event filtering for large datasets
- ✓ Consider virtualization for 50+ resources
- ✓ Batch multiple state updates together
- ✓ Use React.memo for custom resource renderers