Calendar
A month grid to pick a day, several days or a range, in the language and with the today your application passes.
Calendar shows one or more months and lets the reader pick a day, several days or a range. It is
built on react-day-picker and takes all of its props. The package adds
the look, a year and month list built on Select, and two required
props that keep the calendar from guessing: the locale and today. For a date typed or
picked in a form field, use the composed Date, which pairs a field with this calendar.
Chosen: 2026-10-23
// apps/docs/examples/ui/calendar.tsx'use client';
import {useState} from 'react';
import {getDateFnsLocale} from '@workspace/active-format';import {Calendar} from '@workspace/active-ui/components/primitives/calendar';import { NativeSelect, NativeSelectOption,} from '@workspace/active-ui/components/primitives/native-select';
// A fixed "today", so every reader sees the same month. An application// passes the day of its own presentation zone (see the page).const TODAY = new Date(2026, 9, 20);
const LANGUAGES = [ ['en', 'English'], ['nl', 'Dutch'], ['de', 'German'], ['ar-EG', 'Arabic (Egypt)'],] as const;
function isoDay(date: Date | undefined): string { if (!date) return 'none'; const pad = (n: number) => String(n).padStart(2, '0'); return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`;}
/** * One day picked in a month grid. The calendar takes its words, labels and * week start from the locale you pass, and its "today" from you: change the * language to see both follow. The chosen day is printed as an ISO date. */export default function CalendarExample() { const [language, setLanguage] = useState('en'); const [day, setDay] = useState<Date | undefined>(new Date(2026, 9, 23)); return ( <div className="flex flex-col items-center gap-4"> <NativeSelect aria-label="Language" size="sm" value={language} onChange={(event) => setLanguage(event.target.value)} > {LANGUAGES.map(([code, name]) => ( <NativeSelectOption key={code} value={code}> {name} </NativeSelectOption> ))} </NativeSelect> <Calendar mode="single" selected={day} onSelect={setDay} defaultMonth={TODAY} today={TODAY} locale={getDateFnsLocale(language)} className="rounded-md border" /> <p className="text-muted-foreground text-sm"> Chosen: <code>{isoDay(day)}</code> </p> </div> );}Usage#
import {getDateFnsLocale} from '@workspace/active-format';import {Calendar} from '@workspace/active-ui/components/primitives/calendar';
<Calendar mode="single" selected={day} onSelect={setDay} locale={getDateFnsLocale(presentation)} today={today}/>;What your application provides#
locale(required): a date-fns locale, fromgetof active-format for your resolved presentation. It decides the month and day names, the first day of the week and the digits. The accessible labels ("previous month", "today") come from react-day-picker for English, Dutch, German, French and Spanish, and from the browser'sDate Fns Locale Intldata for any other language, so no locale is refused. Without a locale the calendar would render US English.today(required): the reader's current day as a local-midnightDate, in the time zone of your presentation, for exampledatefrom active-format. It marks today, opens the first month and bounds the default navigation. The calendar does not read the runtime clock, which would follow the device's zone instead of the one your application presents.From Iso Date(today Iso Date(time Zone)) The selection, its mode and its type:
mode="single"gives aDate,"multiple"an array,"range"a{from, to}object.
A range, disabled days and lists#
From 2026-10-26 to 2026-11-04
// apps/docs/examples/ui/calendar-range.tsx'use client';
import {useState} from 'react';
import {getDateFnsLocale} from '@workspace/active-format';import {Calendar} from '@workspace/active-ui/components/primitives/calendar';
const TODAY = new Date(2026, 9, 20);
/** The shape of a range in `mode="range"`: its first and last day. */interface DateRange { from: Date | undefined; to?: Date | undefined;}const LOCALE = getDateFnsLocale('en');
function isoDay(date: Date | undefined): string { if (!date) return '…'; const pad = (n: number) => String(n).padStart(2, '0'); return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`;}
/** * A range over two months, with the days before today and the weekends * disabled, and month and year chosen from lists. The modes, the disabled * matcher and the range type are react-day-picker's; the calendar passes * them through. */export default function CalendarRangeExample() { const [range, setRange] = useState<DateRange | undefined>({ from: new Date(2026, 9, 26), to: new Date(2026, 10, 4), }); return ( <div className="flex flex-col items-center gap-4"> <Calendar mode="range" selected={range} onSelect={setRange} numberOfMonths={2} defaultMonth={TODAY} today={TODAY} locale={LOCALE} disabled={[{before: TODAY}, {dayOfWeek: [0, 6]}]} captionLayout="dropdown" startMonth={new Date(2026, 0, 1)} endMonth={new Date(2030, 11, 1)} className="rounded-md border" /> <p className="text-muted-foreground text-sm"> From <code>{isoDay(range?.from)}</code> to{' '} <code>{isoDay(range?.to)}</code> </p> </div> );}mode="range"picks a first and last day;numbershows several months beside each other on a wide screen and below each other on a narrow one.Of Months disabledtakes react-day-picker's matchers: dates,{before},{after},{day, or a function. A disabled day cannot be chosen and is skipped by the arrow keys.Of Week} captionreplaces the month caption with a month and a year list, betweenLayout="dropdown" startandMonth end. The lists are this package'sMonth Select, so a list of many years scrolls in the package's scroll area instead of a browser popup.
Accessibility and keyboard#
The days form a grid: the arrow keys move by a day or a week,
HomeandEndto the start and end of the week,Page UpandPage Downby a month, withShiftby a year.EnterorSpacechooses.Each day is a button named by its full date; today and the chosen days are announced as such.
In a right-to-left language the navigation arrows turn around.
API#
Import from @workspace/
Props
- Type
DayPicker Locale
The date-fns locale of your presentation, for example get from active-format. It sets the month and day names, the first day of the week and the digits; the accessible labels follow its language. Required: without it DayPicker renders US English.
- Type
Date
The reader's current day, as a local-midnight Date in the time zone of your presentation, for example date. It marks today, opens the first month and bounds the default navigation. Required: the calendar does not read the device's clock.
Also takes the props of react-day-picker, unchanged and documented there: ISOWeek, animate, aria-, aria-, auto, broadcast, caption, class, class, components, date, default, dir, disable, disabled, end, first, fixed, footer, formatters, hidden, hide, hide, id, labels, lang, mode, modifiers, modifiers, modifiers, month, nav, nonce, noon, number, numerals, on, on, on, on, on, on, on, on, on, paged, required, reverse, reverse, role, show, show, start, style, styles, time, title, use, use, week.
Takes only the props listed.
Other parts#
CalendarDayButton
Props
Also takes the props of react-day-picker, unchanged and documented there: day, modifiers.
Other props, such as the standard attributes of the underlying element, className and ref, are passed through.
This page adapts the Calendar documentation of shadcn/ui (MIT licence) to this package; see Third-party notices.