Range Calendar
POC of a Range Calendar component using the Base UI DX.
Anatomy
Days
<RangeCalendar.Root>
<RangeCalendar.DayGrid>
<RangeCalendar.DayGridHeader>
{({ days }) =>
days.map((day) => <RangeCalendar.DayGridHeaderCell value={day} />)
}
</RangeCalendar.DayGridHeader>
<RangeCalendar.DayGridBody>
{({ weeks }) =>
weeks.map((week) => (
<RangeCalendar.DayGridRow value={week}>
{({ days }) => days.map((day) => <RangeCalendar.DayCell value={day} />)}
</RangeCalendar.DayGridRow>
))
}
</RangeCalendar.DayGridBody>
</RangeCalendar.DayGrid>
</RangeCalendar.Root>
Months
// Grid layout
<RangeCalendar.Root>
<RangeCalendar.MonthGrid>
{({ months }) => months.map((month) => <RangeCalendar.MonthCell value={month} />)}
</RangeCalendar.MonthGrid>
</RangeCalendar.Root>
// List layout
<RangeCalendar.Root>
<RangeCalendar.MonthList>
{({ months }) => months.map((month) => <RangeCalendar.MonthCell value={month} />)}
</RangeCalendar.MonthList>
</RangeCalendar.Root>
Years
// Grid layout
<RangeCalendar.Root>
<RangeCalendar.YearGrid>
{({ years }) => years.map((year) => <RangeCalendar.YearCell value={year} />)}
</RangeCalendar.YearGrid>
</RangeCalendar.Root>
// List layout
<RangeCalendar.Root>
<RangeCalendar.YearList>
{({ years }) => years.map((year) => <RangeCalendar.YearCell value={year} />)}
</RangeCalendar.YearList>
</RangeCalendar.Root>
Navigation
<RangeCalendar.Root>
<RangeCalendar.SetVisibleYear />
<RangeCalendar.SetVisibleMonth />
</RangeCalendar.Root>
Day Range Calendar
Single visible month
SMTWTFS
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
May 2025
June 2025
SMTWTFS
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
SMTWTFS
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
5
Disable preview
<RangeCalendar.Root disableHoverPreview>{children}</RangeCalendar.Root>
SMTWTFS
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
Recipe: Booking UI
The following demo shows a more advanced use case with lazy-loaded validation data:
May 2025
June 2025
SMTWTFS
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
SMTWTFS
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
5
SMTWTFS
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