Calendar

A date grid in single or range mode, with presets, times, dropdown captions and multiple months. No date library — the grid, weekday names and times all come from Intl.

src/components/ui/calendar.tsx

About

From the component's own source, where it was written.

A date picker grid, in single or range mode.

No date library — the grid, weekday names, month labels and times all come from Intl plus the helpers in lib/date.ts. Always six weeks per month, so paging never changes the height and the layout around it never jumps.

Range picking is drafted before it is committed: the first click sets an anchor, the pointer paints a preview, and the second click (or the release of a drag) confirms. Dragging and clicking are the same gesture here, which is why the release is watched on the window rather than on a cell.

Install

npx astralyx-ui add calendar

Usage

import { Calendar } from '@/components/ui/calendar'

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

// range, with quick presets and two months
<Calendar
  mode="range"
  numberOfMonths={2}
  presets={defaultPresets()}
  selected={range}
  onSelect={setRange}
/>

Composer

Change the props and the source below follows.

October 2026
Props
tsx
<Calendar
  numberOfMonths={1}
  captionLayout="label"
  weekStartsOn={1}
  locale="en-GB"
  onSelect={setValue}
/>

Examples

Single

Range with presets and two months

Dropdown caption and a time

Bounded, no weekends

API

Generated from the source, so it cannot fall behind the code. One table per exported component, then hooks, functions and types.

Calendar

PropTypeDefaultDescription
numberOfMonthsnumber1Months side by side, each with its own caption.
monthDate—The visible month, controlled or not.
defaultMonthDate—The visible month, controlled or not.
onMonthChange(month: Date) => void—The visible month, controlled or not.
weekStartsOnWeekStart1Any weekday, not just Sunday or Monday.
localestring'en-GB'—
fromDateDate—Bounds. Days outside them are disabled, and the arrows stop at the edge.
toDateDate—Bounds. Days outside them are disabled, and the arrows stop at the edge.
disabled(date: Date) => boolean—Arbitrary per-day rule — weekends, holidays, booked dates.
showOutsideDaysbooleantrue—
captionLayout'label' | 'dropdown' | 'label' | 'dropdown''label'A static heading, or month and year selects for jumping years at a time.
showTimebooleanfalseAdds hour and minute selects. Picking a new day keeps the time already chosen.
timeStepnumber5Adds hour and minute selects. Picking a new day keeps the time already chosen.
renderDay(date: Date) => ReactNode—Custom day content (cells grow to fit) and an arbitrary footer.
footerReactNode—Custom day content (cells grow to fit) and an arbitrary footer.
previousMonthLabelstring'Previous month'Accessible name for the previous-month button.
nextMonthLabelstring'Next month'Accessible name for the next-month button.
monthLabelstring'Month'Accessible name for the month dropdown, under captionLayout="dropdown".
yearLabelstring'Year'Accessible name for the year dropdown.
hourLabel(row: string) => string(row) => `${row} hour`Names the hour select, given the row's own label ("Start", "End").
minuteLabel(row: string) => string(row) => `${row} minute`Names the minute select the same way.
classNamestring——
mode'single' | 'range''single'Range mode drafts the selection: the first click anchors, the pointer paints a preview, the second click or the end of a drag commits.
selectedDate | DateRange—Controlled and uncontrolled. Clicking the selected day in single mode clears it.
defaultSelectedDate | DateRange—Controlled and uncontrolled. Clicking the selected day in single mode clears it.
onSelect(date: Date) => void | (range: DateRange) => void—A Date in single mode, a DateRange in range mode. Can be called with undefined when cleared.
presetsCalendarPreset[]—Quick ranges beside the grid. Range mode only. defaultPresets() gives today, last 7, last 30, this and last month.

Types

CalendarPreset

FieldTypeDescription
labelstring—
rangeDateRange—
TypeDefinitionDescription
CalendarMode
'single' | 'range'
A date picker grid, in single or range mode.
WeekStart
0 | 1 | 2 | 3 | 4 | 5 | 6
—