Overview
<Calendar /> is the canonical date primitive in apx-ds — a headless + DOM root for date
selection that powers <DatePicker>, <DateRangePicker>, and scheduler mini-month widgets.
It supports single, multiple, and range modes, locale-aware weekday and month labels, keyboard
navigation, and constraint props (min, max, isDateDisabled).
Overview — single-date selection with min/max bounds
Loading preview…
Overview.tsx
Selection modes
single— one date at a time. The default for date pickers and booking flows.multiple— toggle individual dates on and off. Useful for availability or tag-style date lists.range— pick a start and end date. PassnumberOfMonths={2}for a side-by-side range picker.
Every mode is fully controllable (value + month) or uncontrolled (defaultValue +
defaultMonth).
Variants
Four surface styles for embedding in popovers, sidebars, or inline layouts:
solid— filled background. Default.outline— bordered frame. Pairs well with popover shells.soft— subtle tint without a hard edge.minimal— chromeless grid. For dense inline calendars.
Examples
Basic — single-date selection
Loading preview…
Basic.tsx
Range — two-month range picker
Loading preview…
Range.tsx
Multiple — toggle many dates
Loading preview…
Multiple.tsx
Min / max — bounded selection window
Loading preview…
MinMax.tsx
Disable weekends — custom isDateDisabled
Loading preview…
DisableWeekends.tsx
Variants — solid / outline / soft / minimal
Loading preview…
Variants.tsx
Sizes — sm / md / lg
Loading preview…
Sizes.tsx
Week numbers — ISO week gutter
Loading preview…
WeekNumbers.tsx
Locales — en-US / de-DE / ja-JP
Loading preview…
Locales.tsx
Custom day render — event dots via renderDay
Loading preview…
CustomDayRender.tsx
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| aria-label | string | — | Defines a string value that labels the current element. |
| aria-labelledby | string | — | Identifies the element (or elements) that labels the current element. |
| className | string | — | — |
| color | ResponsiveValue<CalendarColor> | — | — |
| defaultMonth | Date | `new Date()` | Uncontrolled initial visible month. |
| defaultValue | Date | Date[] | DateRange | null | — | Uncontrolled initial value. |
| fixedWeeks | boolean | false | Always render 6 rows (prevents layout shift across months). |
| isDateDisabled | ((d: Date) => boolean) | — | Arbitrary predicate — return `true` to disable the day. Combined OR with `min`/`max`. |
| locale | string | — | BCP-47 locale — drives weekday/month names + first-day-of-week. |
| max | Date | — | Hard upper bound (inclusive). |
| min | Date | — | Hard lower bound (inclusive). |
| mode | enum | 'single' | Selection mode. |
| month | Date | — | Controlled visible month anchor. |
| numberOfMonths | number | 1 (DatePicker: 1, DateRangePicker: 2) | How many months to render side-by-side. |
| onChange | ((value: Date | Date[] | DateRange | null) => void) | — | Fires on any selection mutation. Payload shape mirrors `mode`. |
| onDayHover | ((d: Date) => void) | — | Per-day hover — critical for the range preview UX. |
| onDayLeave | (() => void) | — | Per-day pointer-leave — clears hover preview. |
| onMonthChange | ((d: Date) => void) | — | Fires whenever the visible month changes (nav buttons, year jump, keyboard). |
| renderDay | ((ctx: RenderCalendarDayContext) => ReactNode) | — | Replace the inner contents of every day cell. The default renders the day number. |
| renderHeader | ((ctx: RenderCalendarHeaderContext) => ReactNode) | — | Replace the entire header row (title + nav buttons). |
| renderWeekday | ((ctx: RenderCalendarWeekdayContext) => ReactNode) | — | Replace the weekday label cell (Mon / Tue / …). |
| showOutsideDays | boolean | true | Dim days that spill over from prev/next month. |
| showWeekNumbers | boolean | false | Show the ISO week number column on the leading side. |
| size | ResponsiveValue<CalendarSize> | — | — |
| style | CSSProperties | — | — |
| sx | Sx | — | — |
| translations | Partial<CalendarTranslations> | — | Replace any subset of the default English strings. Merged with `<I18nProvider>`. |
| value | Date | Date[] | DateRange | null | — | Controlled value. Pair with `onChange`. |
| variant | ResponsiveValue<CalendarVariant> | — | — |
| weekStartsOn | enum | — | Override the locale-driven first day of week (0 = Sun … 6 = Sat). |
Accessibility
- Renders an ARIA
gridwithgridcellday buttons — arrow keys, Home/End, PageUp/Down, and Enter/Space follow the W3C Date Picker Dialog keyboard pattern. - Disabled and out-of-range dates are not focusable and expose
aria-disabled. - Navigation buttons in the header have accessible labels derived from locale-aware month titles.
- Week-number gutters are decorative when shown; day cells carry the selectable semantics.
Do / Don't
- Do pair
min/maxwith visible helper text so users know why dates are disabled. - Do use
localeto drive weekday order and month names — no locale data ships with the DS. - Don't rebuild keyboard navigation in
renderDay— the headless layer owns selection and focus; the slot only swaps visuals. - Don't use Calendar for time-of-day picking — it is date-only; reach for a time input or datetime picker instead.