Calendar
Calendar 从 HeroUI v2 到 v3 的迁移指南。
完整的 API 参考、样式指南与高级示例请参阅 v3 Calendar 文档。本指南只关注从 HeroUI v2 的迁移。
结构变化
在 v2 中,Calendar 是一个完全通过 props 配置的单一组件:
import { Calendar } from "@lenso/ui";
export default function App() { return <Calendar aria-label="Date" />;}在 v3 中,Calendar 改用带显式子组件的复合组件模式:
import { Calendar } from "@lenso/ui";
export default function App() { return ( <Calendar aria-label="Date"> <Calendar.Header> <Calendar.Heading /> <Calendar.NavButton slot="previous" /> <Calendar.NavButton slot="next" /> </Calendar.Header> <Calendar.Grid> <Calendar.GridHeader> {(day) => <Calendar.HeaderCell>{day}</Calendar.HeaderCell>} </Calendar.GridHeader> <Calendar.GridBody> {(date) => <Calendar.Cell date={date} />} </Calendar.GridBody> </Calendar.Grid> </Calendar> );}主要变化
1. 组件结构
v2: 单一 Calendar 组件,所有布局都在内部处理
v3: 复合组件:Calendar.Header、Calendar.Heading、Calendar.NavButton、Calendar.Grid、Calendar.GridHeader、Calendar.GridBody、Calendar.HeaderCell、Calendar.Cell、Calendar.CellIndicator
2. 年份选择器
v2: 通过 showMonthAndYearPickers prop 提供内置月份 / 年份选择器
v3: 使用专用复合组件:Calendar.YearPickerTrigger、Calendar.YearPickerGrid、Calendar.YearPickerGridBody、Calendar.YearPickerCell
3. Prop 变更
| v2 prop | v3 等效项 | 说明 |
|---|---|---|
value | value | 保持一致 |
defaultValue | defaultValue | 保持一致 |
onChange | onChange | 保持一致 |
focusedValue | focusedValue | 保持一致 |
onFocusChange | onFocusChange | 保持一致 |
minValue | minValue | 保持一致 |
maxValue | maxValue | 保持一致 |
isDateUnavailable | isDateUnavailable | 保持一致 |
isDisabled | isDisabled | 保持一致 |
isReadOnly | isReadOnly | 保持一致 |
isInvalid | isInvalid | 保持一致 |
visibleMonths | visibleDuration | 改为 {months: number} 对象 |
showMonthAndYearPickers | - | 使用 Calendar.YearPickerTrigger 和 Calendar.YearPickerGrid |
onHeaderExpandedChange | onYearPickerOpenChange | 已重命名 |
color | - | 已移除(请改用 Tailwind CSS) |
calendarWidth | - | 已移除(请改用 className 或 Tailwind CSS) |
weekdayStyle | - | 已移除 |
pageBehavior | pageBehavior | 保持一致 |
firstDayOfWeek | - | 改用 I18nProvider 的 locale |
hideDisabledDates | - | 已移除 |
disableAnimation | - | 已移除 |
topContent | - | 将自定义内容作为 Calendar children 放在 Calendar.Grid 之前 |
bottomContent | - | 将自定义内容作为 Calendar children 放在 Calendar.Grid 之后 |
classNames | - | 在各个复合组件上使用 className |
errorMessage | - | 已移除(请在外部处理校验) |
4. color prop 已移除
v2: color prop 支持 default、primary、secondary、success、warning、danger
v3: 不再提供 color prop,请使用 Tailwind CSS 类设置单元格样式,或通过自定义 calendar.css 覆盖
迁移示例
基本日历
import { Calendar } from "@lenso/ui";import { today, getLocalTimeZone } from "@internationalized/date";
<Calendar aria-label="Date" defaultValue={today(getLocalTimeZone())}/>受控状态
import { useState } from "react";import { Calendar } from "@lenso/ui";import { parseDate } from "@internationalized/date";
const [value, setValue] = useState(parseDate("2024-03-07"));
<Calendar aria-label="Date" value={value} onChange={setValue}/>月份和年份选择器
<Calendar aria-label="Date" showMonthAndYearPickers/>多个月份
<Calendar aria-label="Date" visibleMonths={2}/>不可用日期
import { isWeekend } from "@internationalized/date";import { useLocale } from "@react-aria/i18n";
const { locale } = useLocale();
<Calendar aria-label="Date" isDateUnavailable={(date) => isWeekend(date, locale)}/>顶部与底部内容
<Calendar aria-label="Date" topContent={<p>Select a date</p>} bottomContent={ <button onClick={() => setValue(today(getLocalTimeZone()))}> Today </button> }/>单元格指示器
{/* v2 did not have a built-in cell indicator API */}样式变化
v2:classNames prop
<Calendar classNames={{ base: "custom-base", prevButton: "custom-prev", nextButton: "custom-next", title: "custom-title", cell: "custom-cell", cellButton: "custom-cell-button", }}/>v3:直接使用 className prop
<Calendar className="custom-base"> <Calendar.Header> <Calendar.Heading className="custom-title" /> <Calendar.NavButton slot="previous" className="custom-prev" /> <Calendar.NavButton slot="next" className="custom-next" /> </Calendar.Header> <Calendar.Grid> <Calendar.GridHeader> {(day) => <Calendar.HeaderCell>{day}</Calendar.HeaderCell>} </Calendar.GridHeader> <Calendar.GridBody> {(date) => <Calendar.Cell date={date} className="custom-cell" />} </Calendar.GridBody> </Calendar.Grid></Calendar>组件结构
v3 Calendar 遵循以下结构:
Calendar (Root) ├── [Custom top content] ├── Calendar.Header │ ├── Calendar.Heading (or Calendar.YearPickerTrigger) │ ├── Calendar.NavButton slot="previous" │ └── Calendar.NavButton slot="next" ├── Calendar.Grid (one per visible month) │ ├── Calendar.GridHeader │ │ └── Calendar.HeaderCell (render prop) │ └── Calendar.GridBody │ └── Calendar.Cell (render prop) │ └── Calendar.CellIndicator (optional) ├── Calendar.YearPickerGrid (optional) │ └── Calendar.YearPickerGridBody │ └── Calendar.YearPickerCell └── [Custom bottom content]总结
- 组件结构:单一组件 → 带显式布局控制的复合组件
- 年份选择器:
showMonthAndYearPickersprop → 专用的Calendar.YearPickerTrigger和Calendar.YearPickerGrid组件 - 多个月份:
visibleMonths={n}→visibleDuration={{months: n}},并使用多个带offset的Calendar.Grid组件 - color 已移除:请改用 Tailwind CSS 类
- 顶部 / 底部内容:prop 已移除 → 直接将内容作为 children 放在
Calendar内 - 单元格自定义:新增
Calendar.CellIndicator,且Calendar.Cell支持渲染 prop - 样式:
classNamesprop → 各个复合组件上的className - 已移除 prop:
calendarWidth、weekdayStyle、hideDisabledDates、disableAnimation—— 请使用 Tailwind CSS 或省略