Skip to content

MultiCalendar

MultiCalendar

The MultiCalendar component displays multiple months side by side with synchronized navigation. It supports all three selection modes: single, range, and multiple.

Import

import { MultiCalendar } from '@thaparoyal/calendar-react';
import type { CalendarDate, DateRangeValue } from '@thaparoyal/calendar-react';
import '@thaparoyal/calendar-core/themes/themes.css';

Two Months with Range Selection

The most common use case — range selection across two visible months:

import { useState } from 'react';
import { MultiCalendar } from '@thaparoyal/calendar-react';
import type { DateRangeValue } from '@thaparoyal/calendar-react';
import '@thaparoyal/calendar-core/themes/themes.css';
function MyMultiCalendar() {
const [range, setRange] = useState<DateRangeValue | null>(null);
return (
<div data-theme="amber">
<MultiCalendar.Root
numberOfMonths={2}
mode="range"
config={{ calendarType: 'BS', locale: 'en' }}
value={range}
onValueChange={setRange}
>
<MultiCalendar.Header>
<MultiCalendar.PrevButton />
<MultiCalendar.Title />
<MultiCalendar.NextButton />
</MultiCalendar.Header>
<MultiCalendar.Calendars />
</MultiCalendar.Root>
{range && (
<p>
Start: {range.start?.year}-{range.start?.month}-{range.start?.day}
{''}
End: {range.end?.year}-{range.end?.month}-{range.end?.day}
</p>
)}
</div>
);
}

Three Months

Simply increase numberOfMonths:

<MultiCalendar.Root numberOfMonths={3} mode="range">
<MultiCalendar.Header>
<MultiCalendar.PrevButton />
<MultiCalendar.Title />
<MultiCalendar.NextButton />
</MultiCalendar.Header>
<MultiCalendar.Calendars />
</MultiCalendar.Root>

Selection Modes

Single Selection

Select a single date across multiple visible months:

const [date, setDate] = useState<CalendarDate | null>(null);
<MultiCalendar.Root
numberOfMonths={2}
mode="single"
config={{ calendarType: 'BS', locale: 'en' }}
value={date}
onValueChange={setDate}
>
<MultiCalendar.Header>
<MultiCalendar.PrevButton />
<MultiCalendar.Title />
<MultiCalendar.NextButton />
</MultiCalendar.Header>
<MultiCalendar.Calendars />
</MultiCalendar.Root>

Range Selection

Select a date range with hover preview across months:

const [range, setRange] = useState<DateRangeValue | null>(null);
<MultiCalendar.Root
numberOfMonths={2}
mode="range"
config={{ calendarType: 'BS', locale: 'en' }}
value={range}
onValueChange={setRange}
>
...
</MultiCalendar.Root>

Multiple Selection

Toggle multiple dates on and off:

const [dates, setDates] = useState<CalendarDate[]>([]);
<MultiCalendar.Root
numberOfMonths={2}
mode="multiple"
config={{ calendarType: 'BS', locale: 'en' }}
value={dates}
onValueChange={setDates}
>
...
</MultiCalendar.Root>

Paged Navigation

By default, navigation moves one month at a time. Set pagedNavigation to jump by numberOfMonths:

<MultiCalendar.Root
numberOfMonths={2}
pagedNavigation
mode="range"
config={{ calendarType: 'BS', locale: 'en' }}
>
...
</MultiCalendar.Root>

With numberOfMonths={2} and pagedNavigation, clicking next jumps from Jan-Feb to Mar-Apr (instead of Feb-Mar).

AD Calendar

<MultiCalendar.Root
numberOfMonths={2}
mode="range"
config={{ calendarType: 'AD', locale: 'en' }}
>
...
</MultiCalendar.Root>

Nepali Numerals

<MultiCalendar.Root
numberOfMonths={2}
mode="range"
config={{ calendarType: 'BS', locale: 'ne' }}
>
...
</MultiCalendar.Root>

Disabled Dates

<MultiCalendar.Root
numberOfMonths={2}
mode="range"
disabledDates={[
{ year: 2081, month: 10, day: 10, calendarType: 'BS' },
{ year: 2081, month: 11, day: 15, calendarType: 'BS' },
]}
>
...
</MultiCalendar.Root>

Min/Max Constraints

<MultiCalendar.Root
numberOfMonths={2}
mode="range"
config={{
calendarType: 'BS',
locale: 'en',
minDate: { year: 2081, month: 1, day: 1, calendarType: 'BS' },
maxDate: { year: 2082, month: 6, day: 30, calendarType: 'BS' },
}}
>
...
</MultiCalendar.Root>

Themes

<div data-theme="coral">
<MultiCalendar.Root>...</MultiCalendar.Root>
</div>

Responsive Layout

The core CSS stacks months vertically on small screens:

/* Already included in themes.css */
@media (max-width: 640px) {
.trc-multi-calendar {
flex-direction: column;
}
}

Props

PropTypeDefaultDescription
numberOfMonthsnumber2Number of months to display
mode'single' | 'range' | 'multiple''range'Selection mode
configPartial<CalendarConfig>Calendar configuration
pagedNavigationbooleanfalseNavigate by numberOfMonths at once
valueCalendarDate | CalendarDate[] | DateRangeValue | nullControlled value (type depends on mode)
defaultValuesame as valueInitial value
onValueChange(value) => voidSelection callback
disabledDatesCalendarDate[]Non-selectable dates

Sub-components

ComponentDescription
MultiCalendar.RootRoot provider — manages multi-month state
MultiCalendar.HeaderNavigation header
MultiCalendar.TitleCombined title showing all visible months
MultiCalendar.PrevButtonNavigate backward (1 month or paged)
MultiCalendar.NextButtonNavigate forward (1 month or paged)
MultiCalendar.CalendarsRenders all month grids side by side