A range calendar displays one or more date grids and allows users to select a contiguous range of dates.
Vanilla CSS theme
--tint CSS variable used by the Vanilla CSS examples.May 2026
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
Value
Use the value or defaultValue prop to set the selected date range, using objects in the @internationalized/date package. This library supports parsing date strings in multiple formats, manipulation across international calendar systems, time zones, etc.
February 2025
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
Selected range: February 3 – 12, 2025
import {parseDate, getLocalTimeZone} from '@internationalized/date';
import {useDateFormatter} from 'react-aria/useDateFormatter';
import {RangeCalendar} from './RangeCalendar';
import {useState} from 'react';
function Example() {
let [range, setRange] = useState({
start: parseDate('2025-02-03'),
end: parseDate('2025-02-12')
});
let formatter = useDateFormatter({ dateStyle: 'long' });
return (
<>
<RangeCalendar
value={range}
onChange={setRange}
/>
<p>Selected range: {formatter.formatRange(
range.start.toDate(getLocalTimeZone()),
range.end.toDate(getLocalTimeZone())
)}</p>
</>
);
}
International calendars
By default, RangeCalendar displays the value using the calendar system for the user's locale. Use <I18nProvider> to override the calendar system by setting the Unicode calendar locale extension. The onChange event always receives a date in the same calendar as the value or defaultValue (Gregorian if no value is provided), regardless of the displayed locale.
शक 1946 माघ
| र | सो | मं | बु | गु | शु | श |
|---|---|---|---|---|---|---|
Custom calendar systems
RangeCalendar also supports custom calendar systems that implement custom business rules, for example a fiscal year calendar that follows a 4-5-4 format, where month ranges don't follow the usual Gregorian calendar. See the @internationalized/date docs for an example implementation.
May 2026
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
import type {AnyCalendarDate, Calendar} from '@internationalized/date';
import {CalendarDate, startOfWeek, GregorianCalendar} from '@internationalized/date';
import {RangeCalendar} from './RangeCalendar';
export default function Example() {
return (
<RangeCalendar
firstDayOfWeek="sun"
createCalendar={() => new Custom454()} />
);
}
// See @internationalized/date docs linked above.
Validation
Use the minValue and maxValue props to set the valid date range. The isDateUnavailable callback prevents certain dates from being selected. Use allowsNonContiguousRanges to allow selecting ranges containing unavailable dates. For custom validation rules, set the isInvalid prop and the errorMessage slot.
June 2026
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
Display options
Set the visibleDuration prop and render multiple CalendarGrid elements to display more than one month at a time. The pageBehavior prop controls whether pagination advances by a single month or multiple. The firstDayOfWeek and weeksInMonth props override the locale-specified defaults.
May 2026
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
June 2026
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
firstDayOfWeek
Controlling the focused date
Use the focusedValue or defaultFocusedValue prop to control which date is focused. This controls which month is visible. The onFocusChange event is called when a date is focused by the user.
July 2021
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
import {RangeCalendar} from './RangeCalendar';
import {Button} from './Button';
import {CalendarDate, today, getLocalTimeZone} from '@internationalized/date';
import {useState} from 'react';
function Example() {
let defaultDate = new CalendarDate(2021, 7, 1);
let [focusedDate, setFocusedDate] = useState(defaultDate);
return (
<div>
<Button
style={{marginBottom: 20}}
onPress={() => setFocusedDate(today(getLocalTimeZone()))}>
Today
</Button>
<RangeCalendar
focusedValue={focusedDate}
onFocusChange={setFocusedDate}
/>
</div>
);
}
Month and year pickers
Use the <CalendarMonthPicker> and <CalendarYearPicker> components to allow the user to jump to a different month or year. This example uses the render prop function to render a Select.
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
import {RangeCalendar, CalendarMonthPicker, CalendarYearPicker} from 'react-aria-components/RangeCalendar';
import {CalendarGrid, CalendarCell} from './RangeCalendar';
import {Button} from './Button';
import {Select, SelectItem} from './Select';
import {ChevronLeft, ChevronRight} from 'lucide-react';
<RangeCalendar>
<div className="months">
<div className="month">
<header style={{display: 'flex', gap: 4}}>
<Button slot="previous" variant="quiet">
<ChevronLeft />
</Button>
<CalendarMonthPicker>
{(props) => (
<Select {...props}>
{item => <SelectItem>{item.formatted}</SelectItem>}
</Select>
)}
</CalendarMonthPicker>
<CalendarYearPicker>
{(props) => (
<Select {...props}>
{item => <SelectItem>{item.formatted}</SelectItem>}
</Select>
)}
</CalendarYearPicker>
<Button slot="next" variant="quiet">
<ChevronRight />
</Button>
</header>
<CalendarGrid>
{(date) => <CalendarCell date={date} />}
</CalendarGrid>
</div>
</div>
</RangeCalendar>
API
<RangeCalendar>
<CalendarHeading />
<CalendarMonthPicker />
<CalendarYearPicker />
<Button slot="previous" />
<Button slot="next" />
<CalendarGrid>
<CalendarGridHeader>
{day => <CalendarHeaderCell />}
</CalendarGridHeader>
<CalendarGridBody>
{date => <CalendarCell date={date} />}
</CalendarGridBody>
</CalendarGrid>
<Text slot="errorMessage" />
</RangeCalendar>
RangeCalendar
A range calendar displays one or more date grids and allows users to select a contiguous range of dates.
| Name | Type | Default |
|---|---|---|
visibleDuration | DateDuration | Default: { months: 1 }
|
The amount of days that will be displayed at once. This affects how pagination works. | ||
createCalendar | | Default: — |
A function to create a new
Calendar object for a
given calendar identifier. If not provided, the | ||
commitBehavior | 'clear'
| 'reset'
| 'select' | Default: 'select'
|
Controls the behavior when a pointer is released outside the calendar or a blur occurs mid selection:
| ||
allowsNonContiguousRanges | boolean | Default: — |
When combined with | ||
isDateUnavailable | | Default: — |
Callback that is called for each date of the calendar. If it returns true, then the date is unavailable. The second argument provides the current selection anchor date, if any. This can be used to adjust the available dates based on the user's first selected date. | ||
isDisabled | boolean | Default: false
|
Whether the calendar is disabled. | ||
isReadOnly | boolean | Default: false
|
Whether the calendar value is immutable. | ||
focusedValue | DateValue | null | Default: — |
Controls the currently focused date within the calendar. | ||
defaultFocusedValue | DateValue | null | Default: — |
The date that is focused when the calendar first mounts (uncontrolled). | ||
pageBehavior | PageBehavior | Default: visible
|
Controls the behavior of paging. Pagination either works by advancing the visible page by visibleDuration (default) or one unit of visibleDuration. | ||
firstDayOfWeek | 'sun'
| 'mon'
| 'tue'
| 'wed'
| 'thu'
| 'fri'
| 'sat' | Default: — |
The day that starts the week. | ||
selectionAlignment | 'start'
| 'center'
| 'end' | Default: 'center'
|
Determines the alignment of the visible months on initial render based on the current selection or current date if there is no selection. | ||
weeksInMonth | number | Default: — |
The number of weeks in a month. This overrides the default set by the locale. | ||
children | ChildrenOrFunction | Default: — |
The children of the component. A function may be provided to alter the children based on component state. | ||
value | RangeValue | Default: — |
The current value (controlled). | ||
defaultValue | RangeValue | Default: — |
The default value (uncontrolled). | ||
onChange | | Default: — |
Handler that is called when the value changes. | ||
Default className: react-aria-RangeCalendar
| Render Prop | CSS Selector |
|---|---|
state | CSS Selector: — |
| State of the range calendar. | |
isDisabled | CSS Selector: [data-disabled]
|
| Whether the calendar is disabled. | |
isInvalid | CSS Selector: [data-invalid]
|
| Whether the calendar is invalid. | |
CalendarGrid
A calendar grid displays a single grid of days within a calendar or range calendar which can be keyboard navigated and selected by the user.
| Name | Type | Default |
|---|---|---|
children | ReactElement
| ReactElement | Default: — |
Either a function to render calendar cells for each date in the month,
or children containing a | ||
offset | DateDuration | Default: — |
An offset from the beginning of the visible date range that this CalendarGrid should display. Useful when displaying more than one month at a time. | ||
weekdayStyle | 'narrow'
| 'short'
| 'long' | Default: 'narrow'
|
The style of weekday names to display in the calendar grid header, e.g. single letter, abbreviation, or full day name. | ||
Default className: react-aria-CalendarGrid
CalendarGridHeader
A calendar grid header displays a row of week day names at the top of a month.
| Name | Type | |
|---|---|---|
children | | |
A function to render a | ||
Default className: react-aria-CalendarGridHeader
CalendarHeaderCell
A calendar header cell displays a week day name at the top of a column within a calendar.
| Name | Type | |
|---|---|---|
children | ReactNode | |
The children of the component. | ||
Default className: react-aria-CalendarHeaderCell
CalendarGridBody
A calendar grid body displays a grid of calendar cells within a month.
| Name | Type | |
|---|---|---|
children | | |
A function to render a | ||
Default className: react-aria-CalendarGridBody
CalendarCell
A calendar cell displays a date cell within a calendar grid which can be selected by the user.
| Name | Type | |
|---|---|---|
date | CalendarDate | |
The date to render in the cell. | ||
children | ChildrenOrFunction | |
The children of the component. A function may be provided to alter the children based on component state. | ||
Default className: react-aria-CalendarCell
| Render Prop | CSS Selector |
|---|---|
date | CSS Selector: — |
| The date that the cell represents. | |
formattedDate | CSS Selector: — |
| The day number formatted according to the current locale. | |
isHovered | CSS Selector: [data-hovered]
|
| Whether the cell is currently hovered with a mouse. | |
isPressed | CSS Selector: [data-pressed]
|
| Whether the cell is currently being pressed. | |
isSelected | CSS Selector: [data-selected]
|
| Whether the cell is selected. | |
isSelectionStart | CSS Selector: [data-selection-start]
|
| Whether the cell is the first date in a range selection. | |
isSelectionEnd | CSS Selector: [data-selection-end]
|
| Whether the cell is the last date in a range selection. | |
isFocused | CSS Selector: [data-focused]
|
| Whether the cell is focused. | |
isFocusVisible | CSS Selector: [data-focus-visible]
|
| Whether the cell is keyboard focused. | |
isDisabled | CSS Selector: [data-disabled]
|
Whether the cell is disabled, according to the calendar's minValue, maxValue, and
isDisabled props. Disabled dates are not focusable, and cannot be selected by the user. They
are typically displayed with a dimmed appearance. | |
isOutsideVisibleRange | CSS Selector: [data-outside-visible-range]
|
| Whether the cell is outside the visible range of the calendar. For example, dates before the first day of a month in the same week. | |
isOutsideMonth | CSS Selector: [data-outside-month]
|
| Whether the cell is outside the current month. | |
isUnavailable | CSS Selector: [data-unavailable]
|
Whether the cell is unavailable, according to the calendar's isDateUnavailable prop.
Unavailable dates remain focusable, but cannot be selected by the user. They should be
displayed with a visual affordance to indicate they are unavailable, such as a different color
or a strikethrough.
Note that because they are focusable, unavailable dates must meet a 4.5:1 color contrast ratio,
as defined by WCAG. | |
isInvalid | CSS Selector: [data-invalid]
|
| Whether the cell is part of an invalid selection. | |
isToday | CSS Selector: [data-today]
|
| Whether the cell is today. | |
CalendarHeading
| Name | Type | Default |
|---|---|---|
offset | DateDuration | Default: 0
|
The number of months from the start of the visible range to display. | ||
format | CalendarHeadingFormatOptions | Default: — |
The format of the month heading. | ||
level | number | Default: 3
|
The heading level. | ||
Default className: react-aria-CalendarHeading
CalendarMonthPicker
| Name | Type | |
|---|---|---|
children | | |
A function to render the month picker. | ||
format | 'numeric'
| '2-digit'
| 'long'
| 'short'
| 'narrow' | |
The format of the month. | ||
CalendarYearPicker
| Name | Type | Default |
|---|---|---|
children | | Default: — |
A function to render the year picker. | ||
visibleYears | number | Default: 20
|
The number of years to display. | ||
format | CalendarYearPickerFormatOptions | Default: — |
The format to display. | ||