XDSCalendar@xds/core · Calendar
Preview coming soon

Usage

Calendar lets the user pick a date or date range from a month grid. Use it in booking flows, scheduling UIs, date filters, or anywhere the user needs to see surrounding dates for context.

Best practices

GuidancePractices
DoSet min and max dates to limit selection to a valid window — like only future dates for a booking or the current quarter for a report.
DoUse range mode when the user needs to pick a start and end date, like a trip or a time-off request.
DoUse dateConstraints to disable specific dates like weekends or holidays, and explain why they are unavailable.
DoShow two months side by side when the user frequently selects dates that span a month boundary.
Don'tUse a calendar for dates far in the past or future like a birth date — a text input is faster for open-ended entry.
Don'tDisable large blocks of dates without context — the user should understand why dates are unavailable.

Anatomy

ElementDescription
Month headerrequiredThe month name and year with navigation arrows to move between months.
Day gridrequiredA 7-column grid of days with column headers for the day names.
Selected dayThe currently selected date, highlighted. In range mode, the start and end dates plus the days between them.
Today markerA subtle indicator on the current date for orientation.

Import

ts
import {XDSCalendar} from '@xds/core/Calendar'

Props

PropTypeDescription
mode
'single' | 'range' (default: 'single')Selection mode.
value
ISODateString | DateRangeControlled selected value.
defaultValue
ISODateString | DateRangeUncontrolled default value.
onChange
FunctionSelection callback.
numberOfMonths
1 | 2 (default: 1)Number of months to display.
min
ISODateStringMinimum selectable date.
max
ISODateStringMaximum selectable date.
dateConstraints
Array<(date: Date) => boolean>Custom constraint functions.
focusDate
ISODateStringControlled visible month.
onFocusDateChange
(focusDate: ISODateString) => voidNavigation callback.
hasOutsideDays
boolean (default: true)Show days from adjacent months.
hasWeekNumbers
boolean (default: false)Show ISO week numbers.
hasVariableRowCount
boolean (default: false)Variable vs fixed 6-row grid.
weekStartsOn
0 | 1 | 2 | 3 | 4 | 5 | 6 (default: 0)First day of week (0=Sunday).

Examples

Common configurations, variations, and states.
Calendar — ConstraintsLimit which dates can be selected using min/max bounds and custom rules like weekdays only. Use for scheduling UIs where certain dates are unavailable.
tsx
'use client';
import {useState} from 'react';
import {XDSCalendar, type ISODateString} from '@xds/core/Calendar';
import {XDSStack} from '@xds/core/Layout';
import {XDSText} from '@xds/core/Text';
const isWeekday = (date: Date) => {
const day = date.getDay();
return day !== 0 && day !== 6;
};
export default function CalendarConstraints() {
const [value, setValue] = useState<ISODateString | undefined>(undefined);
return (
<XDSStack direction="vertical" gap={4} hAlign="center">
<XDSText type="supporting" color="secondary">
Jan 10Mar 20, weekdays only
</XDSText>
<XDSCalendar
mode="single"
min={'2026-01-10' as ISODateString}
max={'2026-03-20' as ISODateString}
dateConstraints={[isWeekday]}
value={value}
onChange={val => setValue(val)}
focusDate={'2026-01-01' as ISODateString}
/>
</XDSStack>
);
}
Calendar — RangePick a start and end date with the range highlighted between them. Use for booking dates, time-off requests, or report filters.
tsx
'use client';
import {useState} from 'react';
import {XDSCalendar, type DateRange} from '@xds/core/Calendar';
import {XDSStack} from '@xds/core/Layout';
import {XDSText} from '@xds/core/Text';
export default function CalendarRangeWithValue() {
const [value, setValue] = useState<DateRange>({
start: '2026-01-10',
end: '2026-01-20',
});
return (
<XDSStack direction="vertical" gap={4} hAlign="center">
<XDSText type="supporting" color="secondary">
{value.start && value.end
? `${value.start} → ${value.end}`
: 'Pick a start and end date'}
</XDSText>
<XDSCalendar
mode="range"
value={value}
onChange={range => setValue(range)}
focusDate="2026-01-01"
/>
</XDSStack>
);
}
Calendar — SinglePick one date from a month grid. Use for appointment dates, due dates, or any field that needs a single date.
tsx
'use client';
import {useState} from 'react';
import {XDSCalendar, type ISODateString} from '@xds/core/Calendar';
import {XDSStack} from '@xds/core/Layout';
import {XDSText} from '@xds/core/Text';
export default function CalendarSingle() {
const [value, setValue] = useState<ISODateString>('2026-01-15');
return (
<XDSStack direction="vertical" gap={4} hAlign="center">
<XDSText type="supporting" color="secondary">
{value ? `Selected: ${value}` : 'Pick a date'}
</XDSText>
<XDSCalendar
mode="single"
value={value}
onChange={val => setValue(val)}
focusDate="2026-01-01"
/>
</XDSStack>
);
}
Calendar — Two MonthsTwo months side by side for selecting ranges that span a month boundary. Use in booking or travel UIs where check-in and check-out often fall in different months.
tsx
'use client';
import {useState} from 'react';
import {XDSCalendar, type DateRange} from '@xds/core/Calendar';
import {XDSStack} from '@xds/core/Layout';
import {XDSText} from '@xds/core/Text';
export default function CalendarTwoMonths() {
const [value, setValue] = useState<DateRange>({
start: '2026-01-25',
end: '2026-02-05',
});
return (
<XDSStack direction="vertical" gap={4} hAlign="center">
<XDSText type="supporting" color="secondary">
{value.start && value.end
? `${value.start} → ${value.end}`
: 'Pick a date range'}
</XDSText>
<XDSCalendar
mode="range"
numberOfMonths={2}
value={value}
onChange={range => setValue(range)}
focusDate="2026-01-01"
/>
</XDSStack>
);
}

Showcase source

tsx
'use client';
import {useState} from 'react';
import {XDSCalendar} from '@xds/core/Calendar';
import type {ISODateString} from '@xds/core/Calendar';
export default function CalendarShowcase() {
const [value, setValue] = useState<ISODateString | undefined>('2026-04-15');
return <XDSCalendar mode="single" value={value} onChange={setValue} />;
}