Range Calendar

The React Range Calendar component lets users select a contiguous range of dates from an accessible grid of days. Perfect for booking systems, date range filters, trip planners, and any interface where users need to choose a start and end date with full keyboard and screen reader support.

It is built on top of React Aria Components and our Tailwind-styled registry wrapper in range-calendar.tsx. That wrapper adds a polished header with month navigation, a year picker, and accessible day cells with state-driven styling for range visualization.

Stay dates, May 2026

26
27
28
29
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6

Installation

Install the component using the Tailgrids CLI.

npx @tailgrids/cli add range-calendar

Anatomy

Import the building blocks and compose the range calendar.

import {
  RangeCalendar,
  RangeCalendarHeader,
  RangeNavButton,
  RangeCalendarYearPicker,
  RangeCalendarGrid,
  RangeCalendarGridHeader,
  RangeCalendarGridBody,
  RangeCalendarCell
} from "@/components/tailgrids/core/range-calendar";

export default function RangeCalendarExample() {
  return (
    <RangeCalendar aria-label="Choose a date range">
      <RangeCalendarHeader>
        <RangeNavButton slot="previous" />
        <RangeCalendarYearPicker />
        <RangeNavButton slot="next" />
      </RangeCalendarHeader>
      <RangeCalendarGrid>
        <RangeCalendarGridHeader />
        <RangeCalendarGridBody>
          {date => <RangeCalendarCell date={date} />}
        </RangeCalendarGridBody>
      </RangeCalendarGrid>
    </RangeCalendar>
  );
}

Examples

Default Value

Use defaultValue to initialize the range calendar with a pre-selected date range while keeping it uncontrolled.

Default stay range, November 2024

27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

Controlled

Use value and onChange to fully control the selected date range from React state.

Controlled stay dates, July 2026

28
29
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1

Selected: July 4 – 8, 2026

Disabled Dates

Dates outside minValue and maxValue are rendered as disabled cells and are not selectable. This restricts the selectable date range to a specific window.

Disabled days, May 2026

26
27
28
29
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6

Unavailable Dates

Use isDateUnavailable for marking specific dates as unavailable, such as weekends or blackout dates. Unlike disabled dates, unavailable dates remain focusable but cannot be selected.

Unavailable range, May 2026

26
27
28
29
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6

Allow Non-Contiguous Ranges

Use allowNonContiguousRanges to enable selecting date ranges that include unavailable dates.

Allows non-contiguous ranges, May 2026

26
27
28
29
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6

Validation and Constraints

Combine minValue, maxValue, isDateUnavailable, and isInvalid with a visible helper message to enforce booking constraints and validation rules.

Validation example, May 2026

26
27
28
29
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6

2026-05-27 to 2026-05-29

Valid date range selected

Year Picker

Use RangeCalendarYearPicker component that opens a year menu and updates the focused date. This is a wrapper-specific addition and is not part of React Aria's base API.

Range with year picker, November 2024

27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

Multiple Months

Use visibleDuration to show more than one month at a time in a single calendar.

Responsive range calendar, May to June 2026

26
27
28
29
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
1
2
3
4

International Calendar

The Range Calendar component fully supports internationalization. Use the I18nProvider wrapper to localize the calendar for different regions, languages, and calendar systems.

See here for more information.

التقويم الإسلامي المدني, ذو الحجة ١٤٤٧ هـ

٣٠
١
٢
٣
٤
٥
٦
٧
٨
٩
١٠
١١
١٢
١٣
١٤
١٥
١٦
١٧
١٨
١٩
٢٠
٢١
٢٢
٢٣
٢٤
٢٥
٢٦
٢٧
٢٨
٢٩
٣٠
١
٢
٣
٤

API Reference

RangeCalendar

The root component wraps React Aria's RangeCalendar but exposes the registry wrapper props below.

PropTypeDefaultDescription
valueRangeValue<DateValue> | nullControlled selected date range
defaultValueRangeValue<DateValue> | nullInitial selected date range for uncontrolled usage
onChange(value: RangeValue<DateValue>) => voidCalled when the selected date range changes
minValueDateValueLowest selectable date
maxValueDateValueHighest selectable date
isDateUnavailable(date: DateValue) => booleanMarks specific dates as unavailable
allowsNonContiguousRangesbooleanfalseAllows selecting ranges containing unavailable dates
disabledbooleanfalseDisables the entire calendar
readonlybooleanfalsePrevents changing the selected date range
focusedValueDateValue | nullControlled focused date
defaultFocusedValueDateValue | nullInitial focused date
onFocusChange(date: DateValue) => voidCalled when the focused date changes
isInvalidbooleanWhether the current selection is invalid
pageBehavior"visible" | "single""visible"Controls how paging advances
firstDayOfWeek'sun' | 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat'locale-basedOverrides the first weekday
visibleDuration{ months: number }{ months: 1 }The number of months to display at once
commitBehavior"clear" | "reset" | "select""select"Behavior when pointer is released outside or blur occurs
classNamestringAdditional classes applied to the root
childrenReactNodeCalendar content

RangeCalendarHeader

The header wrapper used for navigation and month/year controls. This is a Tailgrids registry wrapper around a native <header> element, not a React Aria component.

PropTypeDefaultDescription
classNamestringAdditional header classes
childrenReactNodeHeader content

RangeNavButton

The previous and next month buttons. Labels are fixed to Previous month and Next month in the registry wrapper.

PropTypeDefaultDescription
slot"previous" | "next"Chooses the navigation direction
classNamestringAdditional button classes
aria-labelstringauto-generatedAccessible label for the button

RangeCalendarHeading

The centered month and year heading used inside the header row. This is a direct wrapper around React Aria's Heading component.

PropTypeDefaultDescription
classNamestringAdditional heading classes

RangeCalendarYearPicker

An in-header year picker driven by RangeCalendarStateContext. This is a Tailgrids-specific control and is not part of React Aria's public API.

PropTypeDefaultDescription
classNamestringAdditional trigger classes

RangeCalendarGrid

Wraps React Aria's CalendarGrid for rendering the date cells.

PropTypeDefaultDescription
children(date: DateValue) => ReactElementRenders calendar cells for each date
classNamestringAdditional grid classes

RangeCalendarGridHeader

Renders the weekday labels for the calendar grid.

PropTypeDefaultDescription
children(day: string) => ReactNodeRenders a cell for each weekday

RangeCalendarGridBody

Renders the calendar week rows and day cells.

PropTypeDefaultDescription
children(date: DateValue) => ReactNodeRenders a cell for each date

RangeCalendarCell

Renders a date cell for the range calendar.

PropTypeDefaultDescription
dateDateValueThe date represented by the cell
classNamestringAdditional classes applied to the day pill
disabledbooleanOverrides the disabled state data attribute
focusVisiblebooleanOverrides the focus-visible state data attribute
outsideMonthbooleanOverrides the outside-month state data attribute
pressedbooleanOverrides the pressed state data attribute
selectedbooleanOverrides the selected state data attribute
selectionStartbooleanIndicates the cell is the range start
selectionEndbooleanIndicates the cell is the range end

Data attributes exposed by the cell content:

AttributeMeaning
data-selectedThe date is within the selected range
data-selection-startThe date is the start of the selected range
data-selection-endThe date is the end of the selected range
data-disabledThe date is disabled by minValue, maxValue, or disabled
data-focus-visibleThe date has keyboard focus
data-outside-monthThe date belongs to a different month in the grid
data-pressedThe cell is being pressed

Visit React Aria's RangeCalendar documentation for more information.

Accessibility

  • Keyboard support: Users can navigate between days using arrow keys. They can activate range selection with Enter or Space, and extend the selection by holding Shift while navigating.
  • Screen reader support: React Aria provides correct calendar roles, labels, and state announcements for range selection.
  • Disabled and unavailable states: Disabled dates cannot be focused or selected, while unavailable dates remain focusable but blocked from selection.
  • Range visualization: Selection start and end dates are announced distinctly to clarify range boundaries.
  • Year navigation: The custom year picker updates focused calendar state, providing seamless month and year selection.