Components / Calendar and dates
Calendar and dates
Explore every variant and expand each example’s formatted usage code.
Calendar and dates
Independent calendars, date inputs, ranges and time slots.
MonTueWedThuFriSatSun
Usage · TSX
<Calendar
month={month}
focusedDate={focused}
referenceDate="2026-10-24"
selection={{ from: calendarDate, to: calendarDate }}
onMonthChange={setMonth}
onFocusedDateChange={setFocused}
onSelect={setCalendarDate}
/>Working dayNon-workingExceptionInherited
Usage · TSX
<Legend
label="Calendar legend"
items={[
{ id: 'working', label: 'Working day', marker: 'outline' },
{
id: 'closed',
label: 'Non-working',
color: 'var(--rv-ui-text-muted)',
},
{ id: 'exception', label: 'Exception', tone: 'selected' },
{ id: 'inherited', label: 'Inherited', marker: 'dashed' },
]}
/>MonTueWedThuFriSatSun
MonTueWedThuFriSatSun
2–14 nights. October 25 is unavailable.
Usage · TSX
<CalendarPicker
mode="range"
selected={range}
onSelectionChange={setRange}
defaultMonth="2026-10-01"
numberOfMonths={2}
pagedNavigation
min={2}
max={14}
excludeDisabled
isDateDisabled={(date) => date === '2026-10-25'}
referenceDate={reference}
/>
<p class="rv-form-description">
2–14 nights. October 25 is unavailable.
</p>MonTueWedThuFriSatSun
Choose up to five dates.
Usage · TSX
<CalendarPicker
mode="multiple"
selected={multiple}
onSelectionChange={setMultiple}
defaultMonth="2026-10-01"
required
min={1}
max={5}
referenceDate={reference}
/>
<p class="rv-form-description">Choose up to five dates.</p>Oct
2026
MonTueWedThuFriSatSun
Usage · TSX
<CalendarPicker
selected={dropdown}
onSelectionChange={setDropdown}
defaultMonth="2026-10-01"
captionLayout="dropdown"
startMonth="2020-01-01"
endMonth="2030-12-01"
referenceDate={reference}
/>MonTueWedThuFriSatSun
Usage · TSX
<CalendarPicker
selected={preset}
onSelectionChange={(date) => {
setPreset(date);
setPresetError('');
}}
validateSelection={(date) =>
date === '2026-10-25' ? 'Tomorrow is unavailable.' : true
}
onInvalidSelection={setPresetError}
defaultMonth="2026-10-01"
referenceDate={reference}
presets={[
{ label: 'Today', selection: reference },
{ label: 'Tomorrow', selection: '2026-10-25' },
{ label: 'In a week', selection: '2026-10-31' },
]}
/>
{presetError ? <p role="status">{presetError}</p> : null}MonTueWedThuFriSatSun
Usage · TSX
<CalendarPicker
selected={timed}
onSelectionChange={setTimed}
defaultMonth="2026-10-01"
referenceDate={reference}
footer={
<div class="rv-form-grid">
<label class="rv-field">
<span class="rv-field__label">Start time</span>
<DateTimeField
kind="time"
value={start}
onValueChange={setStart}
picker={{
timeFormat: '24h',
text: { chooseTime: 'Choose start time' },
}}
/>
</label>
<label class="rv-field">
<span class="rv-field__label">End time</span>
<DateTimeField
kind="time"
value={end}
onValueChange={setEnd}
picker={{
timeFormat: '24h',
text: { chooseTime: 'Choose end time' },
}}
/>
</label>
</div>
}
/>MonTueWedThuFriSatSun
Usage · TSX
<CalendarPicker
selected={booked}
onSelectionChange={setBooked}
defaultMonth="2026-10-01"
referenceDate={reference}
cellSize={40}
isDateDisabled={(date) =>
date >= '2026-10-12' && date <= '2026-10-15'
}
dayClassName={(date) =>
date >= '2026-10-12' && date <= '2026-10-15'
? 'calendar-booked'
: undefined
}
formatDayLabel={(date, locale) =>
`${Number(date.slice(8, 10))} $100, ${new Intl.DateTimeFormat(locale, { weekday: 'long', month: 'long', day: 'numeric', year: 'numeric', timeZone: 'UTC' }).format(parseIsoDate(date))}`
}
renderDay={(date) => (
<span class="calendar-price">
<span>{Number(date.slice(8, 10))}</span>
<small> $100</small>
</span>
)}
/>#MonTueWedThuFriSatSun
40
41
42
43
44
Usage · TSX
<CalendarPicker
selected={weeks}
onSelectionChange={setWeeks}
defaultMonth="2026-10-01"
showWeekNumber
weekNumbering="iso"
referenceDate={reference}
/>فروردین
۱۴۰۳
شیدسچپج
Usage · TSX
<CalendarPicker
selected={persian}
onSelectionChange={setPersian}
defaultMonth="2024-03-20"
calendarSystem="persian"
locale="fa-IR"
dir="rtl"
weekStartsOn={6}
captionLayout="dropdown"
startMonth="2023-03-21"
endMonth="2027-03-20"
translations={translations}
/>جمادى الأولى
١٤٤٨ هـ
حنثرخجس
Usage · TSX
<CalendarPicker
selected={hijri}
onSelectionChange={setHijri}
defaultMonth="2026-10-24"
calendarSystem="islamic-umalqura"
locale="ar-SA"
dir="rtl"
weekStartsOn={0}
captionLayout="dropdown"
startMonth="2025-01-01"
endMonth="2027-12-31"
translations={{
previousMonth: 'الشهر السابق',
nextMonth: 'الشهر التالي',
chooseMonth: 'اختر الشهر',
chooseYear: 'اختر السنة',
calendar: 'التقويم',
}}
/>MonTueWedThuFriSatSun
The reference instant is October 23 in Los Angeles. Selection remains an ISO date.
Usage · TSX
<CalendarPicker
selected={zone}
onSelectionChange={setZone}
defaultMonth="2026-10-01"
referenceInstant={new Date('2026-10-24T00:30:00Z')}
timeZone="America/Los_Angeles"
showTodayButton
/>
<p class="rv-form-description">
The reference instant is October 23 in Los Angeles. Selection remains
an ISO date.
</p>Feb
2021
MonTueWedThuFriSatSun
Usage · TSX
<CalendarPicker
selected={natural}
onSelectionChange={setNatural}
defaultMonth="2021-02-01"
fixedWeeks={false}
showOutsideDays={false}
disableNavigation
captionLayout="dropdown"
weekStartsOn={1}
/>Live preview
Oct
2026
#MonTueWedThuFriSatSun
40
41
42
43
44
Selected value
Usage · TSX
<div class="catalog-temporal-demo">
<div class="catalog-temporal-layout">
<fieldset class="catalog-temporal-settings">
<legend>Configuration</legend>
<label>
<span>Value</span>
<Dropdown
className="rv-select"
source={[
{ value: 'date', label: 'Date' },
{ value: 'datetime', label: 'Date and time' },
{ value: 'time', label: 'Time' },
]}
value={kind}
onChange={(value) => {
const next = String(value) as typeof kind;
setKind(next);
setValue(null);
if (next !== 'date' && selection === 'multiple')
setSelection('single');
}}
config={{ ariaLabel: 'Value' }}
/>
</label>
<label>
<span>Selection</span>
<Dropdown
className="rv-select"
source={[
{ value: 'single', label: 'Single' },
{ value: 'range', label: 'Range' },
...(kind === 'date'
? [{ value: 'multiple', label: 'Multiple dates' }]
: []),
]}
value={selection}
onChange={(next) => {
setSelection(String(next) as typeof selection);
setValue(null);
}}
config={{ ariaLabel: 'Selection' }}
/>
</label>
<label>
<span>Months</span>
<Dropdown
className="rv-select"
source={[
{ value: '1', label: '1' },
{ value: '2', label: '2' },
{ value: '3', label: '3' },
]}
value={String(months)}
onChange={(next) => setMonths(Number(String(next)))}
config={{ ariaLabel: 'Months' }}
/>
</label>
<label>
<span>Caption</span>
<Dropdown
className="rv-select"
source={[
{ value: 'label', label: 'Label' },
{ value: 'dropdown', label: 'Month/year dropdowns' },
]}
value={caption}
onChange={(next) =>
setCaption(String(next) as typeof caption)
}
config={{ ariaLabel: 'Caption' }}
/>
</label>
<label class="catalog-temporal-check">
<Input
type="checkbox"
checked={weeks}
onChange={(event) => setWeeks(event.currentTarget.checked)}
/>{' '}
Week numbers
</label>
</fieldset>
<div class="catalog-temporal-preview">
<span class="catalog-temporal-caption">Live preview</span>
<TemporalPicker {...options} value={value} onChange={setValue} />
</div>
</div>
<div class="catalog-temporal-result">
<span>Selected value</span>
<output aria-label="Selected date/time value">
{value == null
? 'No date selected'
: typeof value === 'string'
? value
: Array.isArray(value)
? value.join(' · ') || 'No date selected'
: [value.from, value.to].filter(Boolean).join(' → ')}
</output>
</div>
</div>Oct 12–17Oct 12Oct 15+1
Usage · TSX
{renderTemporalValue(h, {
values: ['Oct 12–17'],
fullValue: 'Oct 12, 2026 – Oct 17, 2026',
})}
{renderTemporalValue(h, {
values: ['Oct 12', 'Oct 15', 'Oct 20'],
fullValue: 'Oct 12, 2026; Oct 15, 2026; Oct 20, 2026',
multiple: true,
})}Usage · TSX
<DateTimeField
value={date}
kind="datetime"
onValueChange={setDate}
picker={{
timeFormat: '24h',
calendar: { captionLayout: 'dropdown' },
}}
/>Usage · TSX
{assigneeOpen ? (
<AssigneeField
value={assignees}
options={{
source: [
{ value: 'ana', label: 'Ana', role: 'Engineer' },
{ value: 'bea', label: 'Bea', role: 'Designer' },
],
}}
save={(next) => {
setAssignees(next);
setAssigneeOpen(false);
}}
cancel={() => setAssigneeOpen(false)}
/>
) : (
<Button onClick={() => setAssigneeOpen(true)}>Assign people</Button>
)}
<output>{JSON.stringify(assignees)}</output>Usage · TSX
{lookupOpen ? (
<LookupField
initial={lookup}
context={null}
options={{
dataSource: {
search: async ({ query }) => ({
items: [
{ value: 'launch', label: 'Launch' },
{ value: 'design', label: 'Design' },
].filter((option) =>
option.label.toLowerCase().includes(query.toLowerCase()),
),
}),
resolve: async ({ ids }) =>
ids.map((value) => ({ value, label: String(value) })),
},
}}
apply={(next) => {
setLookup(next);
setLookupOpen(false);
}}
cancel={() => setLookupOpen(false)}
/>
) : (
<Button onClick={() => setLookupOpen(true)}>
Select linked record
</Button>
)}
<output>{JSON.stringify(lookup)}</output>0100 day
day
Usage · TSX
<DurationField
slider={{ max: 100, step: 0.25 }}
unitButtons
defaultUnit="day"
value={duration}
onChange={setDuration}
allowElapsed
/>
<output>{JSON.stringify(duration)}</output>Usage · TSX
<DatePicker
label="Due date"
openLabel="Choose due date"
value={dueDate}
onChange={(next) => {
if (next) setDueDate(next);
}}
/>
<DatePicker
label="Second date"
openLabel="Choose second date"
value={secondDate}
onChange={(next) => {
if (next) setSecondDate(next);
}}
/>Usage · TSX
<DateRangePicker
label="Project dates"
fromLabel="Start date"
toLabel="Finish date"
openLabel="Choose date range"
value={dateRange}
onChange={setDateRange}
/>Usage · TSX
<DateTimeField
aria-label="Date field"
value={fieldDate}
onValueChange={setFieldDate}
picker={{ text: { chooseDate: 'Choose field date' } }}
/>
<DateTimeField
aria-label="Time field"
kind="time"
value={fieldTime}
onValueChange={setFieldTime}
picker={{
timeFormat: '24h',
text: { chooseTime: 'Choose field time' },
}}
/>
<DateTimeField
aria-label="Date and time field"
kind="datetime"
value={fieldDateTime}
onValueChange={setFieldDateTime}
picker={{
timeFormat: '24h',
text: { chooseDate: 'Choose field date and time' },
}}
/>Business hours
09:10–17:00, in 15-minute intervals.12-hour clock with seconds
Explicit confirmation
Usage · TSX
<div>
Business hours
<DateTimeField
kind="time"
aria-label="Business hours"
value={appointment}
onValueChange={setAppointment}
picker={{
timeFormat: '24h',
minTime: '09:10',
maxTime: '17:00',
timeStep: 900,
text: { chooseTime: 'Choose business time' },
}}
/>
</div>
<small>09:10–17:00, in 15-minute intervals.</small>
<div>
12-hour clock with seconds
<DateTimeField
kind="time"
aria-label="Time with seconds"
value={seconds}
onValueChange={setSeconds}
picker={{
timeFormat: '12h',
precision: 'second',
calendar: { locale: 'en-US' },
text: { chooseTime: 'Choose precise time' },
}}
/>
</div>
<div>
Explicit confirmation
<DateTimeField
kind="time"
aria-label="Confirm time"
value={confirmed}
onValueChange={setConfirmed}
picker={{
timeFormat: '24h',
autoApply: false,
text: { chooseTime: 'Choose confirmed time' },
}}
/>
</div>00:0002:0004:0006:0008:0010:0012:0014:0016:0018:0020:0022:00
Mon
Tue
Wed
Thu
Fri
Sat
Sun
SelectedOutside working hoursWeekend
Usage · TSX
<TimeGrid
days={days}
cells={cells}
focused={focused}
weekendDays={[0, 6]}
workingHours={{ startHour: 8, endHour: 18 }}
gridLabel="Availability slots"
hourLabel={(hour) => `${String(hour % 24).padStart(2, '0')}:00`}
cellLabel={(day, start, end, selected) =>
`${day.long} ${start}–${end}, ${selected ? 'selected' : 'unselected'}`
}
matrixRef={matrixRef}
onFocus={setFocused}
{...interaction}
/>
<Legend
label="Availability legend"
items={[
{ id: 'selected', label: 'Selected', tone: 'selected' },
{ id: 'outside', label: 'Outside working hours', tone: 'outside' },
{ id: 'weekend', label: 'Weekend', tone: 'muted' },
]}
/>
<output aria-label="Time selection commits">
{commits} {commits === 1 ? 'change' : 'changes'} committed
</output>