Skip to the content
BooleanPress UI

Form

Calendar

A month grid for choosing a date, several dates or a range of dates.

Import

import { Calendar, CalendarDayButton } from "@booleanpress/ui/calendar"

Also install react-day-picker: pnpm add react-day-picker

Usage

Calendar is React DayPicker with the package's classes. It needs the react-day-picker peer package, which only products that import @booleanpress/ui/calendar install. mode is "single", "multiple" or "range"; selected and onSelect follow the mode (a Date, a Date[] or a { from, to } range).

import { useState } from "react"
import { Calendar } from "@booleanpress/ui/calendar"

export function SendDate() {
  const [date, setDate] = useState<Date | undefined>()
  return <Calendar mode="single" selected={date} onSelect={setDate} />
}

The calendar renders no label of its own: put it under a visible heading, or in a popover whose content has an aria-label. Block days with disabled (a Date, an array, { before }, { after }, { dayOfWeek }, or a function). Limit the months people can reach with startMonth and endMonth; with captionLayout="dropdown", those limits fill the month and year dropdowns. For a date field, put the calendar in a Popover opened by a Button, and close it in onSelect.

The calendar takes its direction from BooleanUIProvider's dir, so in right-to-left the arrow keys follow the reading direction and the month arrows mirror. Dates and month names are formatted with the browser's locale; pass DayPicker's locale to change that.

Examples

Single date

One date chosen, with today marked, in October 2026.

Date range

mode="range": the first click starts the range, the second ends it.

Disabled dates

disabled blocks the days before today and every weekend; they are not focusable by click and cannot be chosen.

Month and year dropdowns

captionLayout="dropdown" replaces the title with month and year selects, limited by startMonth and endMonth.

Date picker in a popover

A button opens the calendar in a Popover; choosing a date sets the button's text and closes it. Escape closes without a change.

Accessibility

Semantics
A table with role="grid" named by the month caption ("October 2026"). Each day is a button named by its full date ("Wednesday, October 14th, 2026"), inside a gridcell with aria-selected when chosen. A chosen day's name ends with ", selected" and today's starts with "Today, ". The month arrows are buttons named "Go to the Previous Month" and "Go to the Next Month".
Labels
Give the calendar a visible heading, or aria-label on the popover or card that holds it. The month and year dropdowns are native selects named "Month" and "Year" by DayPicker.
Focus
The grid is one tab stop: Tab goes to the chosen day, or to today, or to the first day of the month, and the other days are skipped. The arrow keys move focus between days and turn the page at the edges of the month.
Known limits
  • The month and year names, the day names and the month arrows' labels come from DayPicker and the browser's locale, not from BooleanUIProvider's strings. Pass the locale and labels props for another language.
  • A day is 32 px square, which meets WCAG 2.5.8's 24 px.
  • The arrow keys skip disabled days.

Keyboard

Keyboard
KeyBehaviour
ArrowRightMoves focus to the next day. In right-to-left, ArrowLeft moves to the next day instead.
ArrowLeftMoves focus to the previous day. In right-to-left, ArrowRight moves to the previous day instead.
ArrowDownMoves focus to the same weekday in the next week.
ArrowUpMoves focus to the same weekday in the previous week.
HomeMoves focus to the first day of the week.
EndMoves focus to the last day of the week.
PageDownMoves focus to the same day of the next month, and shows that month.
PageUpMoves focus to the same day of the previous month, and shows that month.
ShiftPageDownMoves focus to the same day of the next year.
ShiftPageUpMoves focus to the same day of the previous year.
EnterChooses the focused day.
SpaceChooses the focused day.

API

Calendar

Renders React DayPicker DayPicker and passes it every other prop.

Calendar props
PropTypeDefaultDescription
animatebooleanAnimate navigating between months.
aria-labelstringThe aria-label attribute to add to the container element.
aria-labelledbystringThe aria-labelledby attribute to add to the container element.
autoFocusbooleanWhen a selection mode is set, DayPicker will focus the first selected day (if set) or today's date (if not disabled). Use this prop when you need to focus DayPicker after a user action, for improved accessibility.
broadcastCalendarbooleanDisplay the weeks in the month following the broadcast calendar. Setting this prop will ignore {@link weekStartsOn} (always Monday) and {@link showOutsideDays} will default to true.
buttonVariant"link" | "default" | "destructive" | "outline" | "secondary" | "ghost" | nullghostThe Button variant of the month arrows. Defaults to ghost.
captionLayout"label" | "dropdown" | "dropdown-months" | "dropdown-years"labelShow dropdowns to navigate between months or years. - label: Displays the month and year as a label. Default value. - dropdown: Displays dropdowns for both month and year navigation. - dropdown-months: Displays a dropdown only for the month navigation. - dropdown-years: Displays a dropdown only for the year navigation. Note: By default, showing the dropdown will set the {@link startMonth} to 100 years ago and {@link endMonth} to the end of the current year. You can override this behavior by explicitly setting startMonth and endMonth.
classNamestringClass name to add to the root element.
classNamesPartial<ClassNames>Change the class names used by DayPicker. Use this prop when you need to change the default class names — for example, when importing the style via CSS modules or when using a CSS framework.
componentsPartial<CustomComponents>Change the components used for rendering the calendar elements.
dateLibPartial<DateLib>Replace the default date library with a custom one. Experimental: not guaranteed to be stable (may not respect semver).
defaultMonthDateThe initial month to show in the calendar. Use this prop to let DayPicker control the current month. If you need to set the month programmatically, use {@link month} and {@link onMonthChange}.
dirstringThe text direction of the calendar. Use ltr for left-to-right (default) or rtl for right-to-left.
disabledMatcher | Matcher[]Apply the disabled modifier to the matching days. Disabled days cannot be selected when in a selection mode is set.
disableNavigationbooleanDisable the navigation between months. This prop won't hide the navigation: to hide the navigation, use {@link hideNavigation}.
endMonthDateThe latest month to end the month navigation.
excludeDisabledbooleanWhen true, the range will reset when including a disabled day.
firstWeekContainsDate1 | 4The day of January that is always in the first week of the year.
fixedWeeksbooleanDisplay always 6 weeks per each month, regardless of the month’s number of weeks. Weeks will be filled with the days from the next month.
footerReactNodeAdd a footer to the calendar, acting as a live region. Use this prop to communicate the calendar's status to screen readers. Prefer strings over complex UI elements.
formattersPartial<Formatters>Formatters used to format dates to strings. Use this prop to override the default functions.
hiddenMatcher | Matcher[]Apply the hidden modifier to the matching days. Will hide them from the calendar.
hideNavigationbooleanHide the navigation buttons. This prop won't disable the navigation: to disable the navigation, use {@link disableNavigation}.
hideWeekdaysbooleanHide the row displaying the weekday row header.
idstringA unique id to add to the root element.
ISOWeekbooleanUse ISO week dates instead of the locale setting. Setting this prop will ignore weekStartsOn and firstWeekContainsDate.
labelsPartial<Labels>Labels creators to override the defaults. Use this prop to customize the aria-label attributes in DayPicker.
langstringAdd the language tag to the container element. When omitted, DayPicker uses the active locale code (locale.code). Set this prop to override the language tag.
localePartial<DayPickerLocale>The locale object used to localize dates. Pass a locale from react-day-picker/locale/<code> to localize the calendar.
maxnumberThe maximum number of selectable days. The maximum number of days to include in the range.
minnumberThe minimum number of selectable days. The minimum number of days to include in the range.
mode"single" | "multiple" | "range"Enable the selection of a single day, multiple days, or a range of days.
modifiersRecord<string, Matcher | Matcher[]>Add modifiers to the matching days.
modifiersClassNamesModifiersClassNamesChange the class name for the day matching the modifiers.
modifiersStylesModifiersStylesChange the class name for the day matching the {@link modifiers}.
monthDateThe month displayed in the calendar. As opposed to defaultMonth, use this prop with onMonthChange to change the month programmatically.
navLayout"around" | "after"Adjust the positioning of the navigation buttons. - around: Displays the buttons on either side of the caption. - after: Displays the buttons after the caption. This ensures the tab order matches the visual order. If not set, DayPicker preserves its legacy layout, but the tab order may not align with the visual order when using captionLayout="dropdown".
noncestringA cryptographic nonce ("number used once") which can be used by Content Security Policy for the inline style attributes.
noonSafebooleanKeep calendar math at noon in the configured {@link timeZone} to avoid historical second-level offsets drifting dates across midnight. This prop sets the time of the dates to noon (12:00).
numberOfMonthsnumberThe number of displayed months.
numerals"latn" | "arab" | "arabext" | "deva" | "geez" | "beng" | "guru" | "gujr" | "orya" | "tamldec" | "telu" | "knda" | "mlym" | "thai" | "mymr" | "khmr" | "laoo" | "tibt"The numeral system to use when formatting dates. - latn: Latin (Western Arabic) - arab: Arabic-Indic - arabext: Eastern Arabic-Indic (Persian) - deva: Devanagari - beng: Bengali - guru: Gurmukhi - gujr: Gujarati - orya: Oriya - tamldec: Tamil - telu: Telugu - knda: Kannada - mlym: Malayalam
onDayBlurDayEventHandler<FocusEvent<Element, Element>>Event handler when a day is blurred.
onDayClickDayEventHandler<MouseEvent<Element, MouseEvent>>Event handler when a day is clicked.
onDayFocusDayEventHandler<FocusEvent<Element, Element>>Event handler when a day is focused.
onDayKeyDownDayEventHandler<KeyboardEvent<Element>>Event handler when a key is pressed on a day.
onDayMouseEnterDayEventHandler<MouseEvent<Element, MouseEvent>>Event handler when the mouse enters a day.
onDayMouseLeaveDayEventHandler<MouseEvent<Element, MouseEvent>>Event handler when the mouse leaves a day.
onMonthChangeMonthChangeEventHandlerEvent fired when the user navigates between months.
onNextClickMonthChangeEventHandlerEvent handler when the next month button is clicked.
onPrevClickMonthChangeEventHandlerEvent handler when the previous month button is clicked.
onSelectOnSelectHandler<Date> | OnSelectHandler<Date> | OnSelectHandler<Date[]> | OnSelectHandler<...> | OnSelectHandler<...> | OnSelectHandler<...> | undefinedEvent handler when a day is selected. Event handler when days are selected. Event handler when the selection changes. Event handler when a range is selected.
pagedNavigationbooleanPaginate the month navigation displaying the numberOfMonths at a time.
requiredbooleanWhether the selection is required.
resetOnSelectbooleanWhen true, clicking a day starts a new range if there is no current start date or if a range is already complete. In those cases, the clicked day becomes the start of the new range. When required is false, clicking the same day of a single-day range clears the selection. When true, clicking a day starts a new range if there is no current start date or if a range is already complete. In those cases, the clicked day becomes the start of the new range.
reverseMonthsbooleanRender the months in reversed order (when {@link numberOfMonths} is set) to display the most recent month first.
reverseYearsbooleanReverse the order of years in the dropdown when using captionLayout="dropdown" or captionLayout="dropdown-years".
role"dialog" | "application"The role attribute to add to the container element.
selectedDate | Date[] | DateRangeThe selected date. The selected dates. The selected range.
showOutsideDaysbooleantrueShow the outside days (days falling in the next or the previous month). Note: when a {@link broadcastCalendar} is set, this prop defaults to true.
showWeekNumberbooleanShow the week numbers column. Weeks are numbered according to the local week index.
startMonthDateThe earliest month to start the month navigation.
styleCSSPropertiesStyle to apply to the root element.
stylesPartial<Styles>Change the inline styles of the HTML elements.
timeZonestringThe time zone (IANA or UTC offset) to use in the calendar (experimental). See Wikipedia for the possible values.
titlestringAdd a title attribute to the container element.
todayDateThe today’s date. Default is the current date. This date will get the today modifier to style the day.
useAdditionalDayOfYearTokensbooleanEnable YY and YYYY for day of year tokens when formatting or parsing dates.
useAdditionalWeekYearTokensbooleanEnable DD and DDDD for week year tokens when formatting or parsing dates.
weekStartsOn0 | 1 | 2 | 3 | 4 | 5 | 6The index of the first day of the week (0 - Sunday). Overrides the locale's default.

CalendarDayButton

Renders React DayPicker DayButton and passes it every other prop.

CalendarDayButton props
PropTypeDefaultDescription
dayrequiredCalendarDayThe day to render.
modifiersrequiredModifiersThe modifiers to apply to the day.

Every part takes className, merged with its defaults by cn(), and ref, which reaches the element it renders.

Data attributes: data-slot="calendar" (Calendar), and data-day, data-selected-single, data-range-start, data-range-end, data-range-middle.

Theming

Chosen days are --primary; the days between the ends of a range, and today, are --accent; outside days are --muted-foreground. The cell size is the --cell-size custom property (32 px), which you can set on the calendar's className. Inside a Card or Popover, the calendar's own background is transparent.

The tokens its classes read. Change their values in your theme, and it follows.

Theme tokens
TokenUsed for
--accentbackground
--accent-foregroundtext
--backgroundbackground
--controlborder
--inputborder
--muted-foregroundtext
--popoverbackground
--primarybackground
--primary-foregroundtext
--ringborder, focus ring