Calendar

Base component for custom date pickers
Import

Usage

Use Calendar component to create custom date pickers if DatePicker component does not meet your requirements. Calendar supports all DatePicker props and some other props that are listed in props table – check it out to learn about all component features.

By default, Calendar works the same way as DatePicker component but does not include any logic of dates selection:

MoTuWeThFrSaSu
import { Group } from '@mantine/core';
import { Calendar } from '@mantine/dates';
function Demo() {
return (
<Group position="center">
<Calendar />
</Group>
);
}

Custom date pickers

Use Calendar as a base for custom date pickers. For example, you can create a date picker that allows user to pick three or less dates:

MoTuWeThFrSaSu
import dayjs from 'dayjs';
import { useState } from 'react';
import { Group } from '@mantine/core';
import { Calendar } from '@mantine/dates';
function Demo() {
const [selected, setSelected] = useState<Date[]>([]);
const handleSelect = (date: Date) => {
const isSelected = selected.some((s) => dayjs(date).isSame(s, 'date'));
if (isSelected) {
setSelected((current) => current.filter((d) => !dayjs(d).isSame(date, 'date')));
} else if (selected.length < 3) {
setSelected((current) => [...current, date]);
}
};
return (
<Group position="center">
<Calendar
getDayProps={(date) => ({
selected: selected.some((s) => dayjs(date).isSame(s, 'date')),
onClick: () => handleSelect(date),
})}
/>
</Group>
);
}

Another custom date picker example – week picker:

MoTuWeThFrSaSu
import { useState } from 'react';
import { Group } from '@mantine/core';
import { Calendar } from '@mantine/dates';
import dayjs from 'dayjs';
function getDay(date: Date) {
const day = date.getDay();
return day === 0 ? 6 : day - 1;
}
function startOfWeek(date: Date) {
return new Date(date.getFullYear(), date.getMonth(), date.getDate() - getDay(date) - 1);
}
function endOfWeek(date: Date) {
return dayjs(new Date(date.getFullYear(), date.getMonth(), date.getDate() + (6 - getDay(date))))
.endOf('date')
.toDate();
}
function isInWeekRange(date: Date, value: Date | null) {
return value && dayjs(date).isBefore(endOfWeek(value)) && dayjs(date).isAfter(startOfWeek(value));
}
function Demo() {
const [hovered, setHovered] = useState<Date | null>(null);
const [value, setValue] = useState<Date | null>(null);
return (
<Group position="center">
<Calendar
withCellSpacing={false}
getDayProps={(date) => {
const isHovered = isInWeekRange(date, hovered);
const isSelected = isInWeekRange(date, value);
const isInRange = isHovered || isSelected;
return {
onMouseEnter: () => setHovered(date),
onMouseLeave: () => setHovered(null),
inRange: isInRange,
firstInRange: isInRange && date.getDay() === 1,
lastInRange: isInRange && date.getDay() === 0,
selected: isSelected,
onClick: () => setValue(date),
};
}}
/>
</Group>
);
}

Static prop

Set static prop to display a calendar that user cannot interact with. It is useful when you want to display data with in calendar view but do not want it to be interactive.

MoTuWeThFrSaSu
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
1
import { Group, Indicator } from '@mantine/core';
import { Calendar } from '@mantine/dates';
function Demo() {
return (
<Group position="center">
<Calendar
static
renderDay={(date) => {
const day = date.getDate();
return (
<Indicator size={6} color="red" offset={-2} disabled={day !== 16}>
<div>{day}</div>
</Indicator>
);
}}
/>
</Group>
);
}

Calendar component props

NameTypeDescription
ariaLabels
CalendarAriaLabels
aria-label attributes for controls on different levels
columnsToScroll
number
Number of columns to scroll when user clicks next/prev buttons, defaults to numberOfColumns
date
Date
Date that is displayed, used for controlled component
decadeLabelFormat
string | ((startOfDecade: Date, endOfDecade: Date) => ReactNode)
dayjs label format to display decade label or a function that returns decade label based on date value, defaults to "YYYY"
defaultDate
Date
Initial date that is displayed, used for uncontrolled component
defaultLevel
"month" | "year" | "decade"
Initial level displayed to the user (decade, year, month), used for uncontrolled component
excludeDate
(date: Date) => boolean
Callback function to determine whether the day should be disabled
firstDayOfWeek
0 | 1 | 2 | 3 | 4 | 5 | 6
number 0-6, 0 – Sunday, 6 – Saturday, defaults to 1 – Monday
getDayAriaLabel
(date: Date) => string
Assigns aria-label to days based on date
getDayProps
(date: Date) => Partial<DayProps>
Adds props to Day component based on date
getMonthControlProps
(date: Date) => Partial<PickerControlProps>
Adds props to month picker control based on date
getYearControlProps
(date: Date) => Partial<PickerControlProps>
Adds props to year picker control based on date
hideOutsideDates
boolean
Determines whether outside dates should be hidden, defaults to false
hideWeekdays
boolean
Determines whether weekdays row should be hidden, defaults to false
level
"month" | "year" | "decade"
Current level displayed to the user (decade, year, month), used for controlled component
locale
string
dayjs locale, defaults to value defined in DatesProvider
maxDate
Date
Maximum possible date
maxLevel
"month" | "year" | "decade"
Max level that user can go up to (decade, year, month), defaults to decade
minDate
Date
Minimum possible date
minLevel
"month" | "year" | "decade"
Min level that user can go down to (decade, year, month), defaults to month
monthLabelFormat
string | ((month: Date) => ReactNode)
dayjs label format to display month label or a function that returns month label based on month value, defaults to "MMMM YYYY"
monthsListFormat
string
dayjs format for months list
nextIcon
ReactNode
Change next icon
nextLabel
string
aria-label for next button
numberOfColumns
number
Number of columns to render next to each other
onDateChange
(date: Date) => void
Called when date changes
onLevelChange
(level: CalendarLevel) => void
Called when level changes
onMonthMouseEnter
(event: MouseEvent<HTMLButtonElement, MouseEvent>, date: Date) => void
Called when mouse enters month control
onMonthSelect
(date: Date) => void
Called when user clicks month on year level
onNextDecade
(date: Date) => void
Called when next decade button is clicked
onNextMonth
(date: Date) => void
Called when next month button is clicked
onNextYear
(date: Date) => void
Called when next year button is clicked
onPreviousDecade
(date: Date) => void
Called when previous decade button is clicked
onPreviousMonth
(date: Date) => void
Called when previous month button is clicked
onPreviousYear
(date: Date) => void
Called when previous year button is clicked
onYearMouseEnter
(event: MouseEvent<HTMLButtonElement, MouseEvent>, date: Date) => void
Called when mouse enters year control
onYearSelect
(date: Date) => void
Called when user clicks year on decade level
previousIcon
ReactNode
Change previous icon
previousLabel
string
aria-label for previous button
renderDay
(date: Date) => ReactNode
Controls day value rendering
size
"xs" | "sm" | "md" | "lg" | "xl"
Component size
static
boolean
Determines whether days should be static, static days can be used to display month if it is not expected that user will interact with the component in any way
weekdayFormat
string | ((date: Date) => ReactNode)
dayjs format for weekdays names, defaults to "dd"
weekendDays
DayOfWeek[]
Indices of weekend days, 0-6, where 0 is Sunday and 6 is Saturday, defaults to value defined in DatesProvider
withCellSpacing
boolean
Determines whether controls should be separated by spacing, true by default
yearLabelFormat
string | ((year: Date) => ReactNode)
dayjs label format to display year label or a function that returns year label based on year value, defaults to "YYYY"
yearsListFormat
string
dayjs format for years list

Calendar component Styles API

NameStatic selectorDescription
calendar.mantine-Calendar-calendarCalendar root element
calendarHeader.mantine-Calendar-calendarHeaderCalendar header root element
calendarHeaderControl.mantine-Calendar-calendarHeaderControlPrevious/next calendar header controls
calendarHeaderControlIcon.mantine-Calendar-calendarHeaderControlIconIcon of previous/next calendar header controls
calendarHeaderLevel.mantine-Calendar-calendarHeaderLevelLevel control (changes levels when clicked, month -> year -> decade)
decadeLevelGroup.mantine-Calendar-decadeLevelGroupGroup of decades levels
decadeLevel.mantine-Calendar-decadeLevelDecade level root element
pickerControl.mantine-Calendar-pickerControlButton used to pick months and years
yearsList.mantine-Calendar-yearsListYears list table element
yearsListRow.mantine-Calendar-yearsListRowYears list row element
yearsListCell.mantine-Calendar-yearsListCellYears list cell element
yearLevelGroup.mantine-Calendar-yearLevelGroupGroup of year levels
yearLevel.mantine-Calendar-yearLevelYear level root element
monthsList.mantine-Calendar-monthsListMonths list table element
monthsListRow.mantine-Calendar-monthsListRowMonths list table row element
monthsListCell.mantine-Calendar-monthsListCellMonths list table cell element
monthLevelGroup.mantine-Calendar-monthLevelGroupGroup or month levels
monthLevel.mantine-Calendar-monthLevelMonth level root element
monthThead.mantine-Calendar-monthTheadthead element of month table
monthRow.mantine-Calendar-monthRowtr element of month table
monthTbody.mantine-Calendar-monthTbodytbody element of month table
monthCell.mantine-Calendar-monthCelltd element of month table
month.mantine-Calendar-monthMonth table element
weekdaysRow.mantine-Calendar-weekdaysRowWeekdays tr element
weekday.mantine-Calendar-weekdayWeekday th element
day.mantine-Calendar-dayMonth day control