Mosmox UI
Current version
GitHubnpmjs.com
Navigation & Selection

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
/>

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 is Date[].
  • 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 — native Date values (default).
  • iso — ISO 8601 strings, suitable for APIs and storage.
  • timestamp — Unix timestamps in milliseconds.
  • locale — localized strings using the selected locale.

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

  • locale controls month names, weekday names, date formatting and built-in labels. Supported values are en (default), uk, de and fr.
  • weekStartsOn accepts 0 through 6; 0 is Sunday and 1 is Monday.
  • size accepts sm, default or lg.
  • fullWidth makes the calendar or input fill its container.
  • renderDay can 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

PropTypeDefaultDescription
aria-labelstringCalendarAccessible name for the calendar surface and input.
classNamestring—Additional class name on the root element.
viewwidget | inputwidgetAlways-visible calendar or input popover.
closeOnRangeSelectionbooleantrueFor view="input" and selectionMode="range", closes after the end date is selected. When false, keeps the popover open and shows Close and OK actions.
granularityday | month | yeardaySelect a day, month, or year. Month and year values are normalized to their first day.
variantstandard | ministandardFull month calendar or compact nearby-days strip.
selectionModesingle | multiple | rangesingleSelection behavior and value shape.
valueDate | Date[] | CalendarRange | null—Controlled selected value.
defaultValueDate | Date[] | CalendarRange | nullnullInitial uncontrolled value.
onChange(value) => void—Called after selection changes.
valueFormatdate | iso | timestamp | localedateFormat returned through onChange.
outputDateFormatIntl.DateTimeFormatOptions{ day: '2-digit', month: '2-digit', year: 'numeric' }Format used with valueFormat="locale".
displayDateDate—Controlled month shown by the calendar.
defaultDisplayDateDatecurrent monthInitial month shown in uncontrolled mode.
onDisplayDateChange(date) => void—Called when the visible month changes.
months1 | 2 | 31Number of visible months in the standard variant.
miniReferenceDateDatedefaultValue date or current dateCenter date used by the mini variant.
miniDaysBeforenumber3Number of days shown before the mini calendar reference date.
miniDaysAfternumber3Number of days shown after the mini calendar reference date.
orientationhorizontal | verticalhorizontalLayout for multiple months in the standard variant.
minDate / maxDateDate—Inclusive selectable date limits.
referenceDateDatecurrent dateBoundary used by relativeDateMode.
relativeDateModeany | past | future | currentanyAllows any dates, dates up to the reference date, dates from the reference date onward, or only the period containing the reference date.
disabledDatesDate[] | predicate—Dates or predicate that cannot be selected.
showHolidaysbooleanfalseShow holiday markers and names in the standard month grid.
holidaysArray<{ date: Date; label: string }>[]Holiday dates and the labels shown to users. Multiple holidays may share a date.
holidayInteractionhover | click | bothbothHow users reveal holiday names.
showOutsideDaysbooleantrueShow days belonging to adjacent months.
showWeekNumbersbooleanfalseShow calendar week numbers in the standard month grid.
showTodaybooleantrueShow a Today action.
yearOverviewbooleanfalseDisplay all twelve months of the selected year in one compact calendar.
yearNavigation`arrowsselect`arrows
yearRange{ start: number; end: number }current year ± 10Inclusive range of years displayed by yearNavigation="select".
previousYearContent / nextYearContentReactNode—Optional visible content rendered beside the always-visible previous/next arrow icons.
showClearbooleanfalseShow a Clear action.
footerButtonAlignstart | endstartSide where footer action buttons are placed.
footerButtonOrdertoday-clear | clear-todaytoday-clearOrder of Today and Clear.
footerOppositeContentReactNode—Custom content in the opposite footer section.
showRangePresetsbooleanfalseShow the quick range menu on the left in the standard month grid.
rangePresetsArray<{ label: string; days: number }>Last 7/30/60/90/180 daysReplaces the default quick-range options. Invalid or less-than-one-day options are disabled.
localeen | uk | de | frenLanguage for month, weekday, date and built-in UI labels.
placeholderstringSelect a datePlaceholder for view="input".
monthFormatIntl.DateTimeFormatOptions{ month: 'long', year: 'numeric' }Format for month headings in the standard variant.
Header month/year controls—enabledClick the month or year label in the standard variant to select from a tile grid.
weekStartsOn0..60First day of the week in the standard month grid (0 Sunday, 1 Monday).
sizesm | default | lgdefaultCalendar density.
fullWidthbooleanfalseStretch to the available width.
disabledbooleanfalseDisables navigation and selection.
readOnlybooleanfalseKeeps 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.