7.5 KiB
Calendar
(no submodules)
- calendar.test-fixtures — Wave-3h local test fixture…-
calendar.test-fixtures — Wave-3h local test fixture that augments the chassis test i18n instance with the
react-ui.calendar.*keyset. The chas… -
calendar.variants —
calendarVariantsis the cva config that powers the outer wrapper of<Calendar>. The recipe is intentionally minimal… -
calendar.test-fixtures — Wave-3h local test fixture…
-
calendar.test-fixtures — Wave-3h local test fixture that augments the chassis test i18n instance with the
react-ui.calendar.*keyset. The chas… -
calendar.variants —
calendarVariantsis the cva config that powers the outer wrapper of<Calendar>. The recipe is intentionally minimal… -
calendar.test-fixtures — Wave-3h local test fixture…
-
calendar.test-fixtures — Wave-3h local test fixture that augments the chassis test i18n instance with the
react-ui.calendar.*keyset. The chas… -
calendar.variants —
calendarVariantsis the cva config that powers the outer wrapper of<Calendar>. The recipe is intentionally minimal… -
calendar.test-fixtures — Wave-3h local test fixture…
-
calendar.test-fixtures — Wave-3h local test fixture that augments the chassis test i18n instance with the
react-ui.calendar.*keyset. The chas… -
calendar.variants —
calendarVariantsis the cva config that powers the outer wrapper of<Calendar>. The recipe is intentionally minimal… -
calendar.test-fixtures — Wave-3h local test fixture that augments the chassis test i18n instance with the
react-ui.calendar.*keyset. The chas… -
calendar.variants —
calendarVariantsis the cva config that powers the outer wrapper of<Calendar>. The recipe is intentionally minimal…
Purpose
<Calendar> is the chassis date-grid primitive — a thin wrapper over react-day-picker (v9) that adds the chassis cva recipe, theme-aware lucide chevrons for previous/next-month navigation, locale-driven aria-label overrides, and a labelled outer wrapper. The chassis derives the active locale from useTranslation() so date formatting and accessible labels stay in lock-step with the rest of the app surface.
The chassis exposes the upstream surface verbatim through Omit<DayPickerProps, "className" | "locale"> — every supported mode (single, multiple, range), the selected / onSelect controlled API, numberOfMonths, showOutsideDays, weekStartsOn, disabled, fromMonth/toMonth, the modifiers system, and the rest of the upstream API documented at https://daypicker.dev. Two upstream props are intercepted: className (so it merges with the chassis recipe via cn()) and locale (so the chassis can drive it from useI18n() rather than the consumer wiring it manually). For the rare case where a single calendar must diverge from the active app locale, pass a localeOverride (a Partial<DayPickerLocale> per the upstream API).
Features
- Wraps
react-day-pickerv9 with zero additional state — fully controlled or uncontrolled per the upstream API. - Three modes —
single/multiple/range— selected via the upstreammodeprop. - Locale-aware: the chassis reads the active locale from
useTranslation()so the calendar stays in sync with the app surface. aria-labelon the outer wrapper resolves through the active i18n vialabelKey(defaults toreact-ui.calendar.label).- Previous / next month navigation buttons get translated
aria-labels viapreviousMonthKey/nextMonthKey. - Lucide-iconography for navigation chevrons (
ChevronLeftIcon/ChevronRightIcon) wired intoreact-day-picker'scomponents.Chevronslot. - Forwards refs to the outer wrapper
<div>. - All other upstream props pass through unchanged.
Usage: Basic Example
import { Calendar } from "@suaveplan/react-ui";
import { useState } from "react";
export function ScheduleCalendar() {
const [date, setDate] = useState<Date | undefined>(new Date());
return <Calendar mode="single" selected={date} onSelect={setDate} />;
}
Usage: Advanced Example
import { Calendar } from "@suaveplan/react-ui";
import type { DateRange } from "react-day-picker";
import { useState } from "react";
export function BookingCalendar() {
const [range, setRange] = useState<DateRange | undefined>();
const today = new Date();
return (
<Calendar
mode="range"
selected={range}
onSelect={setRange}
numberOfMonths={2}
showOutsideDays
disabled={{ before: today }}
weekStartsOn={1}
previousMonthKey="react-ui.calendar.previousMonth"
nextMonthKey="react-ui.calendar.nextMonth"
/>
);
}
API Reference
<Calendar>
forwardRef<HTMLDivElement, CalendarProps> — renders an outer wrapper <div role="group" aria-label={…}> containing the <DayPicker> instance.
CalendarProps
| Prop | Type | Default | Description |
|---|---|---|---|
mode |
"single" | "multiple" | "range" |
undefined |
Selection mode — drives the selected / onSelect shape per the upstream API. |
labelKey |
TranslationKey |
"react-ui.calendar.label" |
aria-label for the outer wrapper. |
previousMonthKey |
TranslationKey |
"react-ui.calendar.previousMonth" |
aria-label for the previous-month navigation button. |
nextMonthKey |
TranslationKey |
"react-ui.calendar.nextMonth" |
aria-label for the next-month navigation button. |
localeOverride |
Partial<DayPickerLocale> |
undefined |
Override the date-fns locale for this calendar instance. When unset, react-day-picker falls back to its bundled enUS. |
every other DayPickerProps field |
upstream | upstream | Forwarded as-is. See https://daypicker.dev. |
Implementation Notes
- The chassis intentionally does NOT expose the upstream
localeprop directly —localeOverrideis a renamed escape hatch that documents the chassis's intent to drive locale fromuseTranslation()by default. react-day-pickerships its own classnames for the grid, day buttons, and navigation chrome via its internalclassNamesmap. The chassis only scopes the OUTER container — overriding the inner classnames belongs in a theme variant override.- Keyboard navigation (arrow keys, Home/End, Enter/Space, PageUp/Down) is supplied entirely by
react-day-picker— the chassis does not wrap or intercept it. - The chevron icons are passed via
components.Chevronrather thanclassNamesso the chassis can swap them for theme-provided lucide / radix icons in a future Wave 5d theme-icon-pack pass. react-day-pickerrenders its day grid as either a<table>(default) or a[role="grid"]element depending on the upstream version — the chassis does not assume one or the other in tests, hitting both via thegridselector.- When migrating from a previous
<Calendar>consumer (e.g. an upstream shadcn block), the only required change is to drop thelocaleprop — the chassis derives it automatically. - Per the brief reconciliation note: the chassis casts the unreachable
?? "default"fallback for(i18n as { readonly locale: string }).localeis NOT needed here because the locale is read indirectly viauseTranslation()rather than fromi18n.locale.