Components
A HeroUI range calendar for selecting a contiguous span of dates, built on react-aria. Supports default and controlled values, min/max bounds, unavailable and non-contiguous ranges, read-only and disabled states, per-day indicators, and multiple visible months. Month names are rendered in English.
npx @21st-dev/cli add hero_ui/heroui-range-calendarLoading preview...
"use client"
import type { DateValue } from "@internationalized/date"
import { RangeCalendar } from "@/components/ui/heroui-range-calendar"
import { Description } from "@heroui/react"
import { getLocalTimeZone, today } from "@internationalized/date"
import { I18nProvider } from "react-aria-components"
export default function AllowsNonContiguousRanges() {
const now = today(getLocalTimeZone())
const blockedRanges = [
[now.add({ days: 2 }), now.add({ days: 5 })],
[now.add({ days: 12 }), now.add({ days: 13 })],
] as const
const isDateUnavailable = (date: DateValue) => {
return blockedRanges.some(([start, end]) => date.compare(start) >= 0 && date.compare(end) <= 0)
}
return (
<I18nProvider locale="en-US">
<div className="flex w-full flex-col items-center gap-4 p-8">
<RangeCalendar
allowsNonContiguousRanges
aria-label="Trip dates"
defaultValue={{ end: now.add({ days: 9 }), start: now.add({ days: 1 }) }}
firstDayOfWeek="mon"
isDateUnavailable={isDateUnavailable}
>
<RangeCalendar.Header>
<RangeCalendar.Heading />
<RangeCalendar.NavButton slot="previous" />
<RangeCalendar.NavButton slot="next" />
</RangeCalendar.Header>
<RangeCalendar.Grid>
<RangeCalendar.GridHeader>
{(day) => <RangeCalendar.HeaderCell>{day}</RangeCalendar.HeaderCell>}
</RangeCalendar.GridHeader>
<RangeCalendar.GridBody>
{(date) => <RangeCalendar.Cell date={date} />}
</RangeCalendar.GridBody>
</RangeCalendar.Grid>
</RangeCalendar>
<Description className="text-center">
Non-contiguous ranges are allowed across unavailable dates
</Description>
</div>
</I18nProvider>
)
}
Loading preview...
Loading preview...
Loading preview...
Loading preview...
Loading preview...
Loading preview...
Loading preview...
Loading preview...