Introduction
Calendar with single, multiple, and range selection—Temporal dates, optional time editing, and keyboard-friendly interaction.
@reactleaf/calendar is a date and optional-time picker for React. It targets the same product niche as react-infinite-calendar, but the implementation is new: built for React 19, with @js-temporal/polyfill for values.
Compared with react-infinite-calendar
Spiritual successor, not a drop-in replacement:
- Values: Props expect
Temporal.PlainDateorTemporal.PlainDateTimeonly—notDateor raw ISO strings. Parse strings at your app boundary withTemporal.PlainDate.from(...)/Temporal.PlainDateTime.from(...)(or your own conversion into those types). - Time: Optional
includeTimeadds header time fields, direct hour/minute input, and a dedicated time subview (scroll picker). Date-only flows stay on plain dates; time is minute-precision wall time, not IANA time zones. - Modes: First-class
single,multiple, andrangeon one component (modediscriminant). - Stable shell: The card height is stabilized with CSS tokens so switching between day, month, and time views does not resize the shell, even as the infinite-scroll month list grows.
- Accessibility: Grid-oriented ARIA for the day body, localized labels via
locale+ overridablemessages.
Features
- Modes:
single,multiple, andrangeselection. - Dates:
Temporal.PlainDate/Temporal.PlainDateTimeonly; turn ISO or other formats into those types before passing them in. - Optional time:
includeTimeenables header time editing and the time subview when you need clock times. - Bounds:
minDate/maxDate, plus per-day disabling in single and multiple (isDateDisabled). Range uses bounds only (no per-day blacklist). - Accessibility: Focus management, ARIA on key regions, and keyboard navigation for the day grid.
Requirements
- React 19+ and react-dom (peers).
@js-temporal/polyfill(dependency alongside this package) forTemporalin environments that lack it.- Styles: Import the package stylesheet so layout and tokens apply (see below).
Install
The package is published as @reactleaf/calendar. It ships ESM, TypeScript types, and a stylesheet entry.
Use your package manager of choice, e.g. pnpm add @reactleaf/calendar @js-temporal/polyfill, or npm install @reactleaf/calendar @js-temporal/polyfill, or yarn add @reactleaf/calendar @js-temporal/polyfill. Peers: react, react-dom.
Import the default styles once (path may vary by bundler):
import '@reactleaf/calendar/index.css'Theme hooks such as --calendar-color-accent, --calendar-body-height, and related tokens live in the bundled CSS; override them in your own stylesheet after the import if you need branding or density tweaks.
Minimal usage
import { useState } from 'react'
import type { DateValue } from '@reactleaf/calendar'
import { Calendar } from '@reactleaf/calendar'
import '@reactleaf/calendar/index.css'
export function Demo() {
const [date, setDate] = useState<DateValue | null>(null)
return <Calendar mode="single" value={date} onSelect={setDate} />
}