ProComponents, templates & AI tooling
HeroUI
27.7k

RangeCalendar 范围日历

基于 React Aria RangeCalendar 的可组合日期范围选择器,包含月份网格、导航与年份选择支持。

用法

import { RangeCalendar } from '@heroui/react';

组件结构

import {RangeCalendar} from '@heroui/react';

export default () => (
  <RangeCalendar aria-label="Trip dates">
    <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>
)

示例

禁用

年份选择

RangeCalendar.YearPickerTrigger, RangeCalendar.YearPickerGrid, and their body/cell subcomponents provide an integrated year navigation pattern.

默认值

受控组件

日期范围限制

不可用日期

使用 isDateUnavailable 屏蔽周末、节假日或已预订等不可用日期。

基于锚点的不可用日期

选择范围时,isDateUnavailable 会收到第二个参数 anchorDate(首个选中日期)。可用它限制哪些结束日期有效(例如起始日期后 7 天内)。

月份周数

weeksInMonth 设为固定值(例如 6),在月份切换时保持网格高度稳定。

周视图

设置 visibleDuration={{ weeks: n }} 一次显示一个或多个周。导航按可见周范围前进。显示多周时,使用 pageBehavior="single" 每次移动一周。

日视图

设置 visibleDuration={{ days: n }} 显示连续日期的滚动窗口。导航按可见日范围前进。显示多天时,使用 pageBehavior="single" 每次移动一天。

非连续范围

启用 allowsNonContiguousRanges 以允许跨越不可用日期进行选择。

只读

无效状态

聚焦值

单元格标记

可自定义 RangeCalendar.Cell 的子内容,并使用 RangeCalendar.CellIndicator 展示事件等元数据。

典型场景

多月份展示

结合 visibleDurationoffset 渲染多个网格,适用于预订与规划场景。

国际化日历

默认情况下,RangeCalendar 使用用户 locale 的历法系统显示日期。可用 I18nProvider 包裹组件,并设置 Unicode 历法 locale 扩展 覆盖。

以下示例展示印度历法系统:

注意: 无论显示 locale 如何,onChange 事件始终返回与 valuedefaultValue 相同历法系统的日期(未提供 value 时为公历)。

自定义样式

Tailwind CSS

全局 CSS

若要自定义组件类,可使用 @layer components 指令。了解更多

@layer components {
  .range-calendar {
    @apply w-80 rounded-2xl border border-border bg-surface p-3 shadow-sm;
  }

  .range-calendar__heading {
    @apply text-sm font-semibold text-default;
  }

  .range-calendar__cell[data-selected="true"] .range-calendar__cell-button {
    @apply bg-accent text-accent-foreground;
  }
}

样式参考

HeroUI 遵循 BEM 方法论,确保组件变体与状态可复用且易于自定义。

CSS 类

RangeCalendar 在 packages/styles/components/range-calendar.csspackages/styles/components/calendar-year-picker.css 中使用以下类:

  • .range-calendar - 根容器。
  • .range-calendar__header - 含导航按钮与标题的头部行。
  • .range-calendar__heading - 当前月份标签。
  • .range-calendar__nav-button - 上一月/下一月导航控件。
  • .range-calendar__grid - 主体日期网格。
  • .range-calendar__grid-header - 星期标题行外层。
  • .range-calendar__grid-body - 日期行外层。
  • .range-calendar__header-cell - 星期标题单元格。
  • .range-calendar__cell - 可交互日期单元格外层。
  • .range-calendar__cell-button - 单元格内的可交互日期按钮。
  • .range-calendar__cell-indicator - 日期单元格内的圆点指示器。
  • .calendar-year-picker__trigger - 年份选择器切换按钮。
  • .calendar-year-picker__trigger-heading - 年份选择触发器内的标题文案。
  • .calendar-year-picker__trigger-indicator - 年份选择触发器内的指示图标。
  • .calendar-year-picker__year-grid - 可选年份的覆盖网格。
  • .calendar-year-picker__year-cell - 单个年份选项。

交互状态

RangeCalendar 同时支持伪类与 React Aria 的 data 属性:

  • 已选中[data-selected="true"]
  • 范围起点[data-selection-start="true"]
  • 范围终点[data-selection-end="true"]
  • 范围内[data-selection-in-range="true"]
  • 今天[data-today="true"]
  • 不可用[data-unavailable="true"]
  • 跨月[data-outside-month="true"]
  • 悬停:hover[data-hovered="true"]
  • 按下:active[data-pressed="true"]
  • 焦点可见:focus-visible[data-focus-visible="true"]
  • 禁用:disabled[data-disabled="true"]

API 参考

RangeCalendar

RangeCalendar 继承 React Aria RangeCalendar 的全部 props。

Prop类型默认值描述
valueRangeValue<DateValue> | null-受控的选中范围。
defaultValueRangeValue<DateValue> | null-初始选中范围(非受控)。
onChange(value: RangeValue<DateValue>) => void-选中变化时调用。
focusedValueDateValue-受控的焦点日期。
onFocusChange(value: DateValue) => void-焦点移动到其它日期时调用。
minValueDateValue历法感知的 1900-01-01可选的最早日期。
maxValueDateValue历法感知的 2099-12-31可选的最晚日期。
weeksInMonthnumber-一个月的周数。该值会覆盖区域设置的默认值。
isDateUnavailable(date: DateValue, anchorDate: CalendarDate | null) => boolean-将日期标记为不可用。anchorDate 为当前范围选择中的首个日期。
firstDayOfWeek'sun' | 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat'-覆盖区域设置的一周起始日。
pageBehavior'visible' | 'single''visible'翻页按可见范围或单步前进。
selectionAlignment'start' | 'center' | 'end''center'初始渲染时按选中项对齐可见范围。
allowsNonContiguousRangesbooleanfalse允许范围跨越不可用日期。
isDisabledbooleanfalse禁用交互与选择。
isReadOnlybooleanfalse内容只读,不可更改选中。
isInvalidbooleanfalse标记为无效以配合校验样式。
visibleDuration{months?: number; weeks?: number; days?: number}{months: 1}可见时间范围。使用 { months: n } 为月视图,{ weeks: n } 为周视图,{ days: n } 为日视图。
defaultYearPickerOpenbooleanfalse内置年份选择器的初始展开状态。
isYearPickerOpenboolean-受控的年份选择器展开状态。
onYearPickerOpenChange(isOpen: boolean) => void-年份选择器展开状态变化时调用。

组合部件

组件描述
RangeCalendar.Header导航与标题的头部容器。
RangeCalendar.Heading可见范围的格式化标题。支持 offset(多月份布局)与 format(月/年/日格式选项)。
RangeCalendar.NavButton上一页/下一页导航(slot="previous"slot="next")。
RangeCalendar.Grid单个月的日期网格(多月份布局支持 offset)。
RangeCalendar.GridHeader星期标题容器。
RangeCalendar.GridBody日期单元格主体容器。
RangeCalendar.HeaderCell星期标签单元格。
RangeCalendar.Cell单个日期单元格。
RangeCalendar.CellIndicator用于自定义元数据的可选指示元素。
RangeCalendar.YearPickerTrigger切换年份选择模式的触发器。
RangeCalendar.YearPickerTriggerHeading年份选择触发器内的本地化标题内容。
RangeCalendar.YearPickerTriggerIndicator年份选择触发器内的切换图标。
RangeCalendar.YearPickerGrid年份选择覆盖网格容器。
RangeCalendar.YearPickerGridBody年份网格单元格的 body 渲染器。
RangeCalendar.YearPickerCell单个年份选项单元格。

年份选择器子组件

年份选择器子组件继承 React Aria useCalendarHeadinguseCalendarYearPicker 的格式化属性。

组件属性类型默认值描述
RangeCalendar.YearPickerTriggerHeadingformatDateFormatterOptions-自定义月/年标题(如 {month: 'short'})。
RangeCalendar.YearPickerTriggerHeadingoffset{months?: number}-相对聚焦日期偏移标题(多月布局)。
RangeCalendar.YearPickerGridformatDateFormatterOptions{year: 'numeric'}自定义年份单元格标签(纪元、历法系统等)。
RangeCalendar.YearPickerGridvisibleYearsnumbermin–max 跨度或 20滑动窗口中显示的年份数量。当同时设置 minValuemaxValue 时,默认为二者之间的完整范围。

RangeCalendar.Cell Render

RangeCalendar.Cellchildren 为函数时,可使用 React Aria 的渲染参数:

Prop类型描述
formattedDatestring单元格日期的本地化文案。
isSelectedboolean该日期是否已选中。
isSelectionStartboolean是否为选中范围的起点。
isSelectionEndboolean是否为选中范围的终点。
isUnavailableboolean该日期是否不可用。
isDisabledboolean单元格是否禁用。
isOutsideMonthboolean是否属于相邻月份。

支持的历法系统及其标识符完整列表见:

  • @internationalized/date — 各日期组件共用的日期类型(CalendarDateCalendarDateTimeZonedDateTime)与工具函数
  • I18nProvider — 为子树覆盖语言环境
  • useLocale — 读取当前语言环境与书写方向

相关组件

本页目录