Examples

Basic

To create a simple calendar, just pass in an events array.

import { EventsCalendar, useEventsCalendar } from 'events-calendar';
import events from '@/data/events.json';

export function BasicExample() {
    // Optional: set initial calendar date
    const calendar = useEventsCalendar({ initialDate: '01-Aug-2024' });

    return <EventsCalendar calendar={calendar} events={events} />;
}

Result

August 2024
Sun
Mon
Tue
Wed
Thu
Fri
Sat
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

Asynchronous data fetching

Set the isFetching prop to true to activate the loading overlay.

import { useState } from 'react';
import { IconRefresh } from '@tabler/icons-react';

import { EventsCalendar, RawCalendarEvent } from 'events-calendar';

import { getEvents } from '@/data/utils';
import { CalendarWrapper } from '@/components';

export function AsyncExample() {
    const [isFetching, setIsFetching] = useState(false);
    const [events, setEvents] = useState<RawCalendarEvent[]>([]);

    // Mock fetch from API
    const fetchData = () => {
        setIsFetching(true);
        setEvents([]);

        setTimeout(() => {
            setEvents(getEvents());
            setIsFetching(false);
        }, 500);
    };

    return (
        <div>
            <Button mb='md' color='indigo' leftSection={<IconRefresh size={20} />} onClick={fetchData}>
                Fetch data
            </Button>
            <CalendarWrapper>
                <EventsCalendar events={events} isFetching={isFetching} />
            </CalendarWrapper>
        </div>
    );
}

Result

July 2025
Sun
Mon
Tue
Wed
Thu
Fri
Sat
29
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2

Responsive overflow handling

The calendar will grow to fill its container. Resize the container below to see the calendar automatically show/hide events based on the available space.

import { EventsCalendar, useEventsCalendar } from 'events-calendar';
import events from '@/data/events.json';

export function ResponsiveExample() {
    // Optional: set initial calendar date
    const calendar = useEventsCalendar({ initialDate: '01-Aug-2024' });

    return (
        <div style={{ height: '550px', resize: 'vertical', border: '1px solid #f00', overflow: 'auto' }}>
            <EventsCalendar calendar={calendar} events={events} />
        </div>
    );
}

Result

Resize the calendar by dragging the bottom-right corner

August 2024
Sun
Mon
Tue
Wed
Thu
Fri
Sat
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

Detail popover

Use the onEventClick and renderPopover props to bind a popover to events.

The renderPopover function provides an object containing the clickedEvent, newEvent (for click & drag event creation) and an onClose function. Make sure to call the onClose function on your popover close event to reset the internal calendar state.

import { EventsCalendar, useEventsCalendar } from 'events-calendar';
import events from '@/data/events.json';

import { DetailPopover } from '@/components';

export function PopoverExample() {
    // Optional: set initial calendar date
    const calendar = useEventsCalendar({ initialDate: '01-Aug-2024' });

    return (
        <EventsCalendar
            calendar={calendar}
            events={events}
            onEventClick={({ togglePopover }) => togglePopover()}
            renderPopover={({ clickedEvent, onClose }) => <DetailPopover event={clickedEvent} onClose={onClose} />}
        />
    );
}

Result

August 2024
Sun
Mon
Tue
Wed
Thu
Fri
Sat
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

Custom header

With the useEventsCalendar hook, we can manage the calendar state externally and create a custom header element.

import { EventsCalendar, useEventsCalendar } from 'events-calendar';
import events from '@/data/events.json';
import classes from './CustomHeader.module.css';

import { DetailPopover } from '@/components';
import { CustomHeader } from './CustomHeader';

export function CustomHeaderExample() {
    const calendar = useEventsCalendar();

    return (
        <div className={classes.wrapper}>
            <CustomHeader calendar={calendar} />
            <EventsCalendar
                noHeader
                events={events}
                calendar={calendar}
                onEventClick={({ openPopover }) => openPopover()}
                renderPopover={({ clickedEvent, onClose }) => <DetailPopover event={clickedEvent} onClose={onClose} />}
            />
        </div>
    );
}

Result

July 2025
Sun
Mon
Tue
Wed
Thu
Fri
Sat
29
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2

Click & drag event creation

To enable click & drag event creation, set enableDragCreation to true. You can then use the onEventCreate callback to handle when the user finishes dragging (for example by opening a popover).

import { useState } from 'react';
import { EventsCalendar, useEventsCalendar } from 'events-calendar';

import groups from '@/data/groups.json';
import fields from '@/data/form-fields.json';
import initialEvents from '@/data/events.json';

import { exampleSubmitHandler } from '@/utils';
import { FormPopover, DetailPopover } from '@/components';
import { HandleSubmitArgs, PopoverType, RawDemoEvent } from '@/types';

export function ClickNDragExample() {
    const [events, setEvents] = useState<RawDemoEvent[]>(initialEvents);
    const [popoverType, setPopoverType] = useState<PopoverType>('view');

    // Get calendar instance
    const calendar = useEventsCalendar({ initialDate: '01-Aug-2024' });

    // Submit handler
    const handleSubmit = (args: HandleSubmitArgs) => exampleSubmitHandler(args, events, setEvents);

    return (
        <EventsCalendar<RawDemoEvent>
            enableDragCreation
            calendar={calendar}
            events={events}
            onEventClick={({ togglePopover }) => {
                setPopoverType('view');
                togglePopover();
            }}
            onEventCreate={({ openPopover }) => {
                openPopover();
                setPopoverType('create');
            }}
            renderPopover={({ clickedEvent, newEvent, onClose }) => {
                return popoverType === 'view' ? (
                    <DetailPopover
                        editable
                        event={clickedEvent}
                        onClose={onClose}
                        setPopoverType={setPopoverType}
                        handleSubmit={handleSubmit}
                    />
                ) : (
                    <FormPopover
                        event={popoverType === 'edit' ? clickedEvent : newEvent}
                        onClose={onClose}
                        groups={groups}
                        fields={fields}
                        handleSubmit={handleSubmit}
                        formType={popoverType === 'reschedule' ? 'edit' : popoverType}
                    />
                );
            }}
        />
    );
}

Result

August 2024
Sun
Mon
Tue
Wed
Thu
Fri
Sat
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

Context menu

Use the renderContextMenu prop to bind a context menu to events. Right click on an event below to see it in action.

import { useState } from 'react';
import { EventsCalendar, RawCalendarEvent, useEventsCalendar } from 'events-calendar';

import { PopoverType } from '@/types';
import { ContextMenu, FormPopover, DetailPopover } from '@/components';
import { ExampleHandleSubmitArgs, exampleSubmitHandler } from '@/utils';

import groups from '@/data/groups.json';
import fields from '@/data/form-fields.json';
import initialEvents from '@/data/events.json';

export function ContextMenuExample() {
	const [events, setEvents] = useState<RawCalendarEvent[]>(initialEvents);
	const [popoverType, setPopoverType] = useState<PopoverType>('view');

	// Optional: set initial calendar date
	const calendar = useEventsCalendar({ initialDate: '01-Aug-2024' });

	const handleSubmit = (args: ExampleHandleSubmitArgs) => exampleSubmitHandler(args, events, setEvents);

	return (
        <EventsCalendar
            calendar={calendar}
            events={events}
            onEventClick={({ togglePopover }) => togglePopover()}
            renderPopover={({ clickedEvent, newEvent, onClose }) => {
                return popoverType === 'view' ? (
                    <DetailPopover
                        editable
                        event={clickedEvent}
                        onClose={onClose}
                        setPopoverType={setPopoverType}
                        handleSubmit={handleSubmit}
                    />
                ) : (
                    <FormPopover
                        event={popoverType === 'edit' ? clickedEvent : newEvent}
                        onClose={onClose}
                        groups={groups}
                        fields={fields}
                        handleSubmit={handleSubmit}
                        formType={popoverType === 'reschedule' ? 'edit' : popoverType}
                    />
                );
            }}
            renderContextMenu={({ event, onClose, openPopover, closeContextMenu }) => (
                <ContextMenu
                    event={event}
                    onClose={onClose}
                    openPopover={openPopover}
                    closeContextMenu={closeContextMenu}
                    setPopoverType={setPopoverType}
                    handleSubmit={handleSubmit}
                />
            )}
        />
    );
}

Result

August 2024
Sun
Mon
Tue
Wed
Thu
Fri
Sat
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

Kitchen sink

Kitchen sink implementation with popover & context menu rendering, click & drag event creation, custom header component and external calendar state management.

import { useState } from 'react';
import { EventsCalendar, Header, useEventsCalendar } from 'events-calendar';

import groups from '@/data/groups.json';
import fields from '@/data/form-fields.json';
import { getEvents } from '@/data/utils';

import { exampleSubmitHandler } from '@/utils';
import { useGetFilteredEvents } from '@/hooks';
import { HandleSubmitArgs, PopoverType, RawDemoEvent } from '@/types';
import { ContextMenu, FormPopover, DetailPopover, FilterControl, CalendarWrapper } from '@/components';

import { CustomControls } from './CustomControls';

// Event generation parameters
const numOfEvents = 200;
const dayRange = 90;

export function KitchenSinkExample() {
    const [events, setEvents] = useState<RawDemoEvent[]>(() => getEvents(numOfEvents, dayRange));
    const [inactiveGroups, setInactiveGroups] = useState<string[]>([]);
    const [popoverType, setPopoverType] = useState<PopoverType>('view');

    // Get calendar instance
    const calendar = useEventsCalendar();

    // Filter events
    const filteredEvents = useGetFilteredEvents({ data: events, inactiveGroups });

    // Submit handler
    const handleSubmit = (args: HandleSubmitArgs) => exampleSubmitHandler(args, events, setEvents);

    return (
        <div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>
            <CustomControls calendar={calendar} setEvents={setEvents} numOfEvents={numOfEvents} />
            <CalendarWrapper>
                <div style={{ height: '100%', display: 'flex', flexDirection: 'column' }}>
                    <Header
                        {...calendar}
                        customControls={
                            <FilterControl
                                filterLabel={fields.group}
                                items={groups}
                                hiddenItems={inactiveGroups}
                                setHiddenItems={setInactiveGroups}
                            />
                        }
                    />
                    <EventsCalendar
                        enableDragCreation
                        noHeader
                        calendar={calendar}
                        events={filteredEvents}
                        onEventClick={({ togglePopover }) => {
                            setPopoverType('view');
                            togglePopover();
                        }}
                        onEventCreate={({ openPopover }) => {
                            openPopover();
                            setPopoverType('create');
                        }}
                        renderPopover={({ clickedEvent, newEvent, onClose }) => {
                            return popoverType === 'view' ? (
                                <DetailPopover
                                    editable
                                    event={clickedEvent}
                                    onClose={onClose}
                                    setPopoverType={setPopoverType}
                                    handleSubmit={handleSubmit}
                                />
                            ) : (
                                <FormPopover
                                    event={popoverType === 'edit' ? clickedEvent : newEvent}
                                    onClose={onClose}
                                    groups={groups}
                                    fields={fields}
                                    handleSubmit={handleSubmit}
                                    formType={popoverType === 'reschedule' ? 'edit' : popoverType}
                                />
                            );
                        }}
                        renderContextMenu={({ event, onClose, openPopover, closeContextMenu }) => (
                            <ContextMenu
                                event={event}
                                onClose={onClose}
                                openPopover={openPopover}
                                closeContextMenu={closeContextMenu}
                                setPopoverType={setPopoverType}
                                handleSubmit={handleSubmit}
                            />
                        )}
                    />
                </div>
            </CalendarWrapper>
        </div>
    );
}

Result

July 2025
Sun
Mon
Tue
Wed
Thu
Fri
Sat
29
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2

On this page