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.tsxAbout
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.
<Calendar
numberOfMonths={1}
captionLayout="label"
weekStartsOn={1}
locale="en-GB"
onSelect={setValue}
/>Examples
Single
<Calendar selected={date} onSelect={setDate} />Range with presets and two months
<Calendar mode="range" numberOfMonths={2} presets={defaultPresets()} />Dropdown caption and a time
<Calendar captionLayout="dropdown" showTime />
Bounded, no weekends
<Calendar fromDate={new Date()} disabled={(d) => [0, 6].includes(d.getDay())} />API
Generated from the source, so it cannot fall behind the code. One table per exported component, then hooks, functions and types.
Calendar
| Prop | Type | Default | Description |
|---|---|---|---|
| numberOfMonths | number | 1 | Months side by side, each with its own caption. |
| month | Date | — | The visible month, controlled or not. |
| defaultMonth | Date | — | The visible month, controlled or not. |
| onMonthChange | (month: Date) => void | — | The visible month, controlled or not. |
| weekStartsOn | WeekStart | 1 | Any weekday, not just Sunday or Monday. |
| locale | string | 'en-GB' | — |
| fromDate | Date | — | Bounds. Days outside them are disabled, and the arrows stop at the edge. |
| toDate | Date | — | 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. |
| showOutsideDays | boolean | true | — |
| captionLayout | 'label' | 'dropdown' | 'label' | 'dropdown' | 'label' | A static heading, or month and year selects for jumping years at a time. |
| showTime | boolean | false | Adds hour and minute selects. Picking a new day keeps the time already chosen. |
| timeStep | number | 5 | Adds 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. |
| footer | ReactNode | — | Custom day content (cells grow to fit) and an arbitrary footer. |
| previousMonthLabel | string | 'Previous month' | Accessible name for the previous-month button. |
| nextMonthLabel | string | 'Next month' | Accessible name for the next-month button. |
| monthLabel | string | 'Month' | Accessible name for the month dropdown, under captionLayout="dropdown". |
| yearLabel | string | '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. |
| className | string | — | — |
| 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. |
| selected | Date | DateRange | — | Controlled and uncontrolled. Clicking the selected day in single mode clears it. |
| defaultSelected | Date | 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. |
| presets | CalendarPreset[] | — | Quick ranges beside the grid. Range mode only. defaultPresets() gives today, last 7, last 30, this and last month. |
Types
CalendarPreset
| Field | Type | Description |
|---|---|---|
| label | string | — |
| range | DateRange | — |
| Type | Definition | Description |
|---|---|---|
CalendarMode | 'single' | 'range' | A date picker grid, in single or range mode. |
WeekStart | 0 | 1 | 2 | 3 | 4 | 5 | 6 | — |