Range Calendar

Date range grid.

Usage

Composes exactly like Calendar; only the selection model differs. value is { start, end } of DateValues, and @internationalized/date is a peerDependency — install it alongside sve-ui.

SMTWTFS
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
31

The two-step interaction

First click sets the start, second sets the end, and hovering between them previews the span. Bits also normalises a backwards selection, so clicking the end before the start does the sensible thing rather than producing an inverted range — which is the bug every hand-rolled range picker ships first.

The styling follows that model: the two endpoints are filled and the days between are a tint, with the inner corners squared off, so the span reads as one continuous band with two handles rather than as a row of separately selected days. The live hover preview uses the same tint as the committed middle, so what you see while choosing is what you get.

Bounding the span

minDays and maxDays bound how long a range may be — a two-night minimum, a fortnight maximum.

excludeDisabled refuses a range that would straddle an unavailable date. That one matters for booking: without it, a user can select across a day that is already taken and the range silently swallows it. "Three nights including the one that is gone" is not a valid answer.

Shared with Calendar

Header, Heading, the nav buttons, Grid, GridHead, GridBody, GridRow, HeadCell, MonthSelect and YearSelect are the same components Calendar uses — Bits re-exports the identical modules to both namespaces, so there is one styled implementation rather than two copies of the same CSS drifting apart. Only Root, Cell and Day are range-specific.

Props

RangeCalendar.Root

PropTypeDefault
value The selected range, as `{ start, end }` of `DateValue`s from `@internationalized/date`. Bindable.{ start: DateValue | undefined; end: DateValue | undefined }
onValueChange Called when the range changes.(value: DateRange) => void
placeholder The month currently on screen. Bindable.DateValue
minValue Earliest selectable date.DateValue
maxValue Latest selectable date.DateValue
minDays Smallest number of days a range may span.number
maxDays Largest number of days a range may span.number
excludeDisabled When true, a range may not straddle an unavailable date — picking one that would is rejected rather than silently swallowing the blocked day.boolean
isDateUnavailable (date: DateValue) => boolean
isDateDisabled (date: DateValue) => boolean
numberOfMonths number1
locale BCP-47 locale driving month names, weekday order and numerals.string'en'
calendarLabel What this calendar is FOR. Bits builds the accessible name as `${calendarLabel} ${month} ${year}` and defaults it to the literal word "Event", so leave it unset and it announces "Event January 2026".string'Event'
disabled booleanfalse
readonly booleanfalse
class Extra classes merged onto the root.string
children Snippet<[SnippetProps]>

The shared parts are documented on the Calendar page.