Calendar
A flexible date calendar for widget and input-based date selection.
Calendar provides a date-selection surface for dashboards, forms and date fields. It supports a standalone widget or an input-style trigger with a calendar popover.
Calendar supports en, uk, de and fr. Set locale on an individual Calendar or set locale once on ConfigProvider to localize Calendar and other supported components globally. A local Calendar locale overrides the provider value.
<ConfigProvider locale="uk">
<Calendar />
</ConfigProvider>Views
Use view="widget" for an always-visible calendar (the default), or view="input" when the calendar should open from an input control.
<Calendar view="widget" />
<Calendar view="input" placeholder="Select a date" />Full year overview
Set yearOverview to display all twelve months of the selected year in a responsive grid. Combine it with fullWidth to use the entire available container width.
<Calendar yearOverview fullWidth defaultDisplayDate={new Date(2026, 0, 1)} />The overview keeps the same date-selection, locale, disabled-date, and value APIs as the regular calendar. It renders three month columns on wide screens and collapses to two and one column as the viewport narrows.
Use yearNavigation="select" when users should choose a year from a list instead of navigating one year at a time. yearRange limits the years shown in that list. Date limits and relative modes are applied to both the year list and the day grid; unavailable years and days are disabled and shown in a muted style. showToday adds a Today action to the year overview.
The year navigation arrows remain visible next to the Select. By default they contain only the previous/next icons. Use previousYearContent and nextYearContent to add custom text or React content beside the arrows; the icons are never replaced.
<Calendar
yearOverview
yearNavigation="select"
yearRange={{ start: 2019, end: 2034 }}
previousYearContent="Back"
nextYearContent="Forward"
minDate={new Date(2026, 2, 1)}
maxDate={new Date(2026, 10, 30)}
showToday
/>Footer actions
Use footerButtonAlign to place the action group at the start or end of the footer. footerButtonOrder accepts today-clear or clear-today. footerOppositeContent renders arbitrary React content in the other side of the same row, such as text, an icon, or an additional button.
<Calendar
showToday
showClear
footerButtonAlign="start"
footerButtonOrder="today-clear"
footerOppositeContent={<span>Additional content</span>}
/><Calendar
showToday
showClear
footerButtonAlign="end"
footerButtonOrder="clear-today"
footerOppositeContent={<span>Additional content</span>}
/>With footerButtonAlign="start", the Today/Clear group is on the left and the opposite content is on the right. With footerButtonAlign="end", the group is on the right and the opposite content is on the left. footerButtonOrder controls which of the two built-in buttons appears first.
Mini calendar
Use variant="mini" for a compact date strip instead of the full month grid. It shows a configurable range of nearby days around miniReferenceDate. The strip displays up to seven days at once; when the range is longer, previous/next controls scroll through the available days. variant="mini" works with both widget and input views and supports single, multiple and range selection modes.
<Calendar
variant="mini"
miniReferenceDate={new Date()}
miniDaysBefore={10}
miniDaysAfter={10}
selectionMode="single"
onChange={(date) => console.log(date)}
/>
<Calendar
variant="mini"
view="input"
selectionMode="range"
miniDaysBefore={4}
miniDaysAfter={4}
placeholder="Choose nearby dates"
/>The Today action returns the strip to the selected or reference date so that it is visible again after scrolling. If there is no selected value, it uses miniReferenceDate or the current date. Use showToday={false} to hide it. The mini variant supports the same selection, controlled-value, output-format, locale and date-constraint APIs as the standard calendar. months, orientation, monthFormat, month/year pickers, week numbers, holidays and range presets apply to the standard month view.
miniReferenceDate is the center date used when the mini calendar is first rendered. If it is omitted, the first date from defaultValue is used when available; otherwise the current date is used. miniDaysBefore and miniDaysAfter are floored to whole non-negative numbers. Seven or fewer total days are shown at once, while longer ranges are browsed with the previous/next controls.
Selection modes
selectionMode="single"— selects one date (default).selectionMode="multiple"— toggles any number of dates. The value isDate[].selectionMode="range"— selects a start and end date. The value is{ from: Date | null, to: Date | null }.
<Calendar selectionMode="single" onChange={(date) => console.log(date)} />
<Calendar selectionMode="multiple" defaultValue={[new Date()]} />
<Calendar selectionMode="range" showClear />The component supports both uncontrolled and controlled usage. Use defaultValue for an initial value managed internally, or value plus onChange when the parent owns the selected value. The value prop always uses the Date-based CalendarValue shape; valueFormat only changes the value emitted by onChange.
const [date, setDate] = useState<Date | null>(new Date());
<Calendar
selectionMode="single"
value={date}
onChange={(next) => setDate(next instanceof Date ? next : null)}
/>Month and year selection
Use granularity="month" when the user should select a month without a day, or granularity="year" when only years are relevant. The selected values are represented by Date objects normalized to the first day of the month or the first day of the year. selectionMode="range" enables month ranges or year ranges.
<Calendar granularity="month" />
<Calendar granularity="month" selectionMode="range" />
<Calendar granularity="year" />
<Calendar view="input" granularity="year" selectionMode="range" placeholder="Choose years" />
<Calendar granularity="month" relativeDateMode="current" referenceDate={new Date()} />
<Calendar granularity="year" relativeDateMode="current" referenceDate={new Date()} />Month and year views use tile grids. minDate and maxDate disable periods outside the inclusive limit; for example, month limits are evaluated together with their year. relativeDateMode="past" allows only periods up to referenceDate, relativeDateMode="future" allows only periods from that reference point onward, and relativeDateMode="current" allows only the period containing the reference point. showToday selects the current month or year in these modes, and showClear resets the selection.
Multiple months
months accepts 1, 2 or 3. The calendars are horizontal by default. Set orientation="vertical" to stack them.
<Calendar months={2} orientation="horizontal" />
<Calendar months={3} orientation="vertical" />To show the previous, current and next month in one row, start the three-month view one month before the current month:
<Calendar
months={3}
orientation="horizontal"
defaultDisplayDate={new Date(new Date().getFullYear(), new Date().getMonth() - 1, 1)}
/>Sizes
Use size="default" for the regular calendar or size="sm" for the compact version. The small size applies to every calendar mode: standard day grid, multiple months, range presets, mini calendar, month selection, year selection and input popovers.
<Calendar size="default" />
<Calendar size="sm" />
<Calendar size="sm" variant="mini" view="input" />
<Calendar size="sm" granularity="month" />
<Calendar size="sm" granularity="year" />Month and year pickers
The month and year labels in the calendar header are interactive. Select the month label to open a 4-column month grid, or select the year label to open a 4-column year grid. Choosing a tile returns to the day view and keeps the selected month or year.
<Calendar />The previous/next month and previous/next year controls remain available in every view. The year picker shows a 16-year window centered around the currently displayed year.
displayDate and onDisplayDateChange can be used to control the visible month independently from the selected value. defaultDisplayDate sets the initial visible month in uncontrolled mode.
Date constraints and display options
Use minDate, maxDate and disabledDates to control which days can be selected. showOutsideDays displays the trailing and leading days from adjacent months. showWeekNumbers adds week numbers, while showToday and showClear add footer actions.
<Calendar
minDate={new Date(2026, 0, 1)}
maxDate={new Date(2026, 11, 31)}
disabledDates={[new Date(2026, 5, 15)]}
showWeekNumbers
showToday
showClear
/>disabledDates may also be a predicate:
<Calendar disabledDates={(date) => date.getDay() === 0 || date.getDay() === 6} />Use relativeDateMode with referenceDate when selection must be limited relative to a specific date. any allows both directions, past allows the reference date and earlier dates, and future allows the reference date and later dates.
<Calendar relativeDateMode="future" referenceDate={new Date()} />
<Calendar relativeDateMode="past" referenceDate={new Date(2026, 8, 15)} />For an absolute allowed period, combine minDate and maxDate. disabledDates can add individual exceptions or a predicate-based rule on top of these limits.
Constraints are applied before selection in every selection mode, including dates rendered from adjacent months. disabled disables navigation and selection entirely; readOnly keeps the calendar visible but prevents changing the value.
Quick range presets
Set showRangePresets to show a quick-range menu on the left side of the calendar. It works with both view="widget" and view="input", and is intended for selectionMode="range". The default menu contains Last 7 days, Last 30 days, Last 60 days, Last 90 days and Last 180 days. Each range includes today.
<Calendar selectionMode="range" showRangePresets />
<Calendar view="input" selectionMode="range" showRangePresets placeholder="Choose a date range" />Pass rangePresets to replace the default menu. days is the length of the range in calendar days, counted back from and including today.
<Calendar
selectionMode="range"
showRangePresets
rangePresets={[
{ label: 'This week', days: 7 },
{ label: 'This month', days: 30 },
{ label: 'This quarter', days: 90 },
]}
/>Output format
By default, onChange returns native Date objects (or arrays/ranges of Date objects). Use valueFormat to choose another output representation:
date— nativeDatevalues (default).iso— ISO 8601 strings, suitable for APIs and storage.timestamp— Unix timestamps in milliseconds.locale— localized strings using the selectedlocale.
outputDateFormat controls the localized representation when valueFormat="locale" is used. For range and multiple selection modes, the same format is applied to every date while preserving the array or { from, to } shape.
<Calendar valueFormat="iso" onChange={(value) => saveToApi(value)} />
<Calendar valueFormat="timestamp" selectionMode="range" onChange={(value) => console.log(value)} />
<Calendar locale="uk" valueFormat="locale" outputDateFormat={{ day: '2-digit', month: 'long', year: 'numeric' }} />Holidays
Use holidays to annotate dates with one or more named holidays. Enable the display with showHolidays. A red dot is rendered below each holiday date. holidayInteraction controls how the holiday names are shown: hover, click or both (the default).
<Calendar
showHolidays
holidayInteraction="both"
holidays={[
{ date: new Date(2026, 8, 24), label: 'Independence Day' },
{ date: new Date(2026, 8, 24), label: 'Company holiday' },
]}
/>Localization and sizing
localecontrols month names, weekday names, date formatting and built-in labels. Supported values areen(default),uk,deandfr.weekStartsOnaccepts0through6;0is Sunday and1is Monday.sizeacceptssm,defaultorlg.fullWidthmakes the calendar or input fill its container.renderDaycan replace the day content while preserving selection and disabled state.
<Calendar
locale="uk"
weekStartsOn={1}
size="sm"
renderDay={(date, state) => state.outside ? `·${date.getDate()}` : date.getDate()}
/>The input view uses the localized formatted value as its read-only field and closes automatically after a single-date selection. Click the input again, click outside the calendar, or press Escape to close the popover. For range selection, closeOnRangeSelection controls what happens after the second date: it defaults to true, so a completed range closes the popover; set it to false to keep the calendar open and show localized Close and OK buttons.
For selectionMode="range", the first click sets from and the second click sets to. Selecting a new date after a completed range starts a new range. If the second date is earlier than the first, the component normalizes the range so the earlier date is from. For selectionMode="multiple", clicking an already selected date removes it.
API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
aria-label | string | Calendar | Accessible name for the calendar surface and input. |
className | string | — | Additional class name on the root element. |
view | widget | input | widget | Always-visible calendar or input popover. |
closeOnRangeSelection | boolean | true | For view="input" and selectionMode="range", closes after the end date is selected. When false, keeps the popover open and shows Close and OK actions. |
granularity | day | month | year | day | Select a day, month, or year. Month and year values are normalized to their first day. |
variant | standard | mini | standard | Full month calendar or compact nearby-days strip. |
selectionMode | single | multiple | range | single | Selection behavior and value shape. |
value | Date | Date[] | CalendarRange | null | — | Controlled selected value. |
defaultValue | Date | Date[] | CalendarRange | null | null | Initial uncontrolled value. |
onChange | (value) => void | — | Called after selection changes. |
valueFormat | date | iso | timestamp | locale | date | Format returned through onChange. |
outputDateFormat | Intl.DateTimeFormatOptions | { day: '2-digit', month: '2-digit', year: 'numeric' } | Format used with valueFormat="locale". |
displayDate | Date | — | Controlled month shown by the calendar. |
defaultDisplayDate | Date | current month | Initial month shown in uncontrolled mode. |
onDisplayDateChange | (date) => void | — | Called when the visible month changes. |
months | 1 | 2 | 3 | 1 | Number of visible months in the standard variant. |
miniReferenceDate | Date | defaultValue date or current date | Center date used by the mini variant. |
miniDaysBefore | number | 3 | Number of days shown before the mini calendar reference date. |
miniDaysAfter | number | 3 | Number of days shown after the mini calendar reference date. |
orientation | horizontal | vertical | horizontal | Layout for multiple months in the standard variant. |
minDate / maxDate | Date | — | Inclusive selectable date limits. |
referenceDate | Date | current date | Boundary used by relativeDateMode. |
relativeDateMode | any | past | future | current | any | Allows any dates, dates up to the reference date, dates from the reference date onward, or only the period containing the reference date. |
disabledDates | Date[] | predicate | — | Dates or predicate that cannot be selected. |
showHolidays | boolean | false | Show holiday markers and names in the standard month grid. |
holidays | Array<{ date: Date; label: string }> | [] | Holiday dates and the labels shown to users. Multiple holidays may share a date. |
holidayInteraction | hover | click | both | both | How users reveal holiday names. |
showOutsideDays | boolean | true | Show days belonging to adjacent months. |
showWeekNumbers | boolean | false | Show calendar week numbers in the standard month grid. |
showToday | boolean | true | Show a Today action. |
yearOverview | boolean | false | Display all twelve months of the selected year in one compact calendar. |
yearNavigation | `arrows | select` | arrows |
yearRange | { start: number; end: number } | current year ± 10 | Inclusive range of years displayed by yearNavigation="select". |
previousYearContent / nextYearContent | ReactNode | — | Optional visible content rendered beside the always-visible previous/next arrow icons. |
showClear | boolean | false | Show a Clear action. |
footerButtonAlign | start | end | start | Side where footer action buttons are placed. |
footerButtonOrder | today-clear | clear-today | today-clear | Order of Today and Clear. |
footerOppositeContent | ReactNode | — | Custom content in the opposite footer section. |
showRangePresets | boolean | false | Show the quick range menu on the left in the standard month grid. |
rangePresets | Array<{ label: string; days: number }> | Last 7/30/60/90/180 days | Replaces the default quick-range options. Invalid or less-than-one-day options are disabled. |
locale | en | uk | de | fr | en | Language for month, weekday, date and built-in UI labels. |
placeholder | string | Select a date | Placeholder for view="input". |
monthFormat | Intl.DateTimeFormatOptions | { month: 'long', year: 'numeric' } | Format for month headings in the standard variant. |
| Header month/year controls | — | enabled | Click the month or year label in the standard variant to select from a tile grid. |
weekStartsOn | 0..6 | 0 | First day of the week in the standard month grid (0 Sunday, 1 Monday). |
size | sm | default | lg | default | Calendar density. |
fullWidth | boolean | false | Stretch to the available width. |
disabled | boolean | false | Disables navigation and selection. |
readOnly | boolean | false | Keeps the calendar visible without allowing selection. |
renderDay | (date, state) => ReactNode | — | Custom day renderer. |
The renderDay state object contains disabled, outside and selected, allowing custom day content to keep the same selection and availability semantics.
Accessibility
The calendar uses labelled navigation buttons, selected-day state, today indication and keyboard-focusable date buttons. The input view exposes aria-expanded and aria-haspopup="dialog"; press Enter or Space to toggle it and Escape to close it. Clicking outside the input calendar also closes the popover. Provide a meaningful aria-label when more than one calendar appears in the same view.
The standard variant uses a month grid and marks unavailable days as disabled. The mini variant exposes its visible date strip as a list and keeps the same disabled-date rules. Always provide an accessible label when using an icon-only or unlabeled calendar surface.