Logo VitNode
Documentation

Calendar

A month grid for picking a day, several days or a date range, localized to the visitor's language out of the box.

The Calendar shows a month and lets people pick dates from it. Use it inline for booking or reporting screens. For a form field that opens on click, reach for the Date Picker instead.

Preview

Usage

import { Calendar } from '@vitnode/core/components/ui/calendar'
const [date, setDate] = React.useState<Date>()

<Calendar mode="single" onSelect={setDate} selected={date} />

Calendar is built on React DayPicker, so every DayPicker prop works.

Date range

Set mode="range" and keep a DateRange in state. numberOfMonths shows months side by side on wider screens and stacks them on phones.

import { Calendar, type DateRange } from '@vitnode/core/components/ui/calendar'
const [range, setRange] = React.useState<DateRange>()

<Calendar mode="range" numberOfMonths={2} onSelect={setRange} selected={range} />

Multiple days

mode="multiple" collects an array of dates. max caps how many can be picked.

<Calendar max={3} mode="multiple" onSelect={setDates} selected={dates} />

Disabled days

disabled takes a date, an array of dates or a matcher. Here: no past days and no weekends.

<Calendar
  disabled={[{ before: new Date() }, { dayOfWeek: [0, 6] }]}
  mode="single"
/>

Month and year dropdowns

Typing a birthday by clicking "previous month" 300 times is nobody's idea of fun. captionLayout="dropdown" adds month and year selects. Set startMonth and endMonth to bound the years.

<Calendar
  captionLayout="dropdown"
  endMonth={new Date()}
  mode="single"
  startMonth={new Date(1926, 0)}
/>

Use dropdown-months or dropdown-years for only one of them.

Week numbers

<Calendar mode="single" showWeekNumber />

Today button

Control the visible month with month and onMonthChange, then jump back from a footer button.

const [month, setMonth] = React.useState(new Date())

<Calendar month={month} onMonthChange={setMonth} mode="single" />
<Button onClick={() => setMonth(new Date())}>Today</Button>

Presets

Presets are plain buttons that set the range and move the month to it. Handy for analytics filters.

<Button
  onClick={() => {
    setRange({ from: addDays(today, -6), to: today })
    setMonth(today)
  }}
>
  Last 7 days
</Button>

Custom day content

Swap the day button through components.DayButton and render CalendarDayButton with extra children. A <span> inside it gets small, muted text automatically. A larger --cell-size makes room for it.

import {
  Calendar,
  CalendarDayButton,
} from '@vitnode/core/components/ui/calendar'

const PricedDayButton = ({
  children,
  ...props
}: React.ComponentProps<typeof CalendarDayButton>) => (
  <CalendarDayButton {...props}>
    {children}
    <span>${priceFor(props.day.date)}</span>
  </CalendarDayButton>
)

<Calendar
  className="[--cell-size:--spacing(11)]"
  components={{ DayButton: PricedDayButton }}
  mode="single"
/>

Define the day button outside your component, so React does not remount every day on each render.

Appointment picker

Pair the Calendar with a list of time slots. Reset the slot when the day changes.

Localization

The Calendar follows the active VitNode language with no setup. Month names, weekday names, the first day of the week and screen reader labels all come from the browser's Intl API, so no extra locale files land in your bundle. In Polish the week starts on Monday, in the US on Sunday.

Need a date-fns locale for something Intl can't do? Add react-day-picker to your app, then pass the locale as locale and the Calendar uses it instead.

import { pl } from 'react-day-picker/locale'

<Calendar locale={pl} mode="single" />

Force a different first day with weekStartsOn={1}.

Accessibility

  • The grid is a real ARIA grid. Arrow keys move by day and week, Page Up and Page Down by month, Home and End to the edges of a week.
  • Each day reads as its full date, plus "Today" and "selected" when they apply.
  • Navigation and dropdown labels are translated through core.global.calendar.
  • Arrows flip in right-to-left languages.

Props

Calendar accepts every DayPicker prop, plus:

Prop

Type

API Reference

React DayPicker