TimeInput
TimeInput → TimeField 从 HeroUI v2 到 v3 的迁移指南。
完整的 API 参考、样式指南与高级示例请参阅 v3 TimeField 文档。本指南只关注从 HeroUI v2 的迁移。
结构变化
在 v2 中,TimeInput 是单个组件,通过 prop 配置:
import { TimeInput } from "@heroui/react";
export default function App() {
return <TimeInput label="Time" name="time" />;
}在 v3 中,TimeField 改为复合组件,需要配合 DateInputGroup 与分段(segment)的 render prop:
import { TimeField, DateInputGroup, Label } from "@heroui/react";
export default function App() {
return (
<TimeField className="w-[256px]" name="time">
<Label>Time</Label>
<DateInputGroup>
<DateInputGroup.Input>
{(segment) => <DateInputGroup.Segment segment={segment} />}
</DateInputGroup.Input>
</DateInputGroup>
</TimeField>
);
}主要变化
1. 组件命名
v2: TimeInput
v3: TimeField
2. 组件结构
v2: 单个组件,通过 prop 配置
v3: 复合组件:TimeField(根)+ DateInputGroup 与 DateInputGroup.Input(render prop)+ DateInputGroup.Segment;可选地搭配 DateInputGroup.Prefix 与 DateInputGroup.Suffix
3. Prop 变更
| v2 prop | v3 位置 | 说明 |
|---|---|---|
label | — | 改用 Label 组件 |
description | — | 改用 Description 组件 |
errorMessage | — | 改用 FieldError 组件 |
value、defaultValue、onChange | TimeField | 与 React Aria 一致 |
minValue、maxValue、granularity、placeholderValue | TimeField | 相同 |
isRequired、isDisabled、isReadOnly、isInvalid、name | TimeField | 相同 |
validationBehavior、shouldForceLeadingZeros | TimeField | 相同 |
variant | DateInputGroup | 简化为仅 primary | secondary |
fullWidth | TimeField 或 DateInputGroup | 设置在根或分组上 |
color | — | 已移除(请改用 Tailwind CSS) |
size | — | 已移除(请改用 Tailwind CSS) |
radius | — | 已移除(请改用 Tailwind CSS) |
labelPlacement | — | 通过布局自行处理 |
startContent | DateInputGroup.Prefix | 改用 Prefix 子组件 |
endContent | DateInputGroup.Suffix | 改用 Suffix 子组件 |
classNames | — | 在 TimeField 与 DateInputGroup 各部分上使用 className |
groupProps | — | 在 DateInputGroup 上使用 className 或标准 DOM 属性 |
labelProps | — | 在 Label 上使用 className |
fieldProps | — | 在 DateInputGroup 上使用 className |
innerWrapperProps | — | 在分组 / 输入相关部分上使用 className |
descriptionProps | — | 在 Description 上使用 className |
errorMessageProps | — | 在 FieldError 上使用 className |
inputRef | — | 由 TimeField / React Aria 处理 ref |
迁移示例
带描述与错误信息
<TimeInput
description="Select start time"
label="Start time"
name="startTime"
/>
<TimeInput
errorMessage="Please enter a valid time"
isInvalid
label="Time"
name="time"
/>import { Description, FieldError, Label } from "@heroui/react";
<TimeField className="w-[256px]" name="startTime">
<Label>Start time</Label>
<DateInputGroup>
<DateInputGroup.Input>
{(segment) => <DateInputGroup.Segment segment={segment} />}
</DateInputGroup.Input>
</DateInputGroup>
<Description>Select start time</Description>
</TimeField>
<TimeField className="w-[256px]" isInvalid name="time">
<Label>Time</Label>
<DateInputGroup>
<DateInputGroup.Input>
{(segment) => <DateInputGroup.Segment segment={segment} />}
</DateInputGroup.Input>
</DateInputGroup>
<FieldError>Please enter a valid time</FieldError>
</TimeField>受控
import { parseTime } from "@internationalized/date";
import { useState } from "react";
const [value, setValue] = useState(null);
<TimeInput
label="Time"
name="time"
value={value}
onChange={setValue}
/>import type { TimeValue } from "@internationalized/date";
import { useState } from "react";
const [value, setValue] = useState<TimeValue | null>(null);
<TimeField
className="w-[256px]"
name="time"
value={value}
onChange={setValue}
>
<Label>Time</Label>
<DateInputGroup>
<DateInputGroup.Input>
{(segment) => <DateInputGroup.Segment segment={segment} />}
</DateInputGroup.Input>
</DateInputGroup>
</TimeField>最小 / 最大值与粒度
import { parseTime } from "@internationalized/date";
<TimeInput
granularity="minute"
label="Time"
maxValue={parseTime("18:00")}
minValue={parseTime("09:00")}
name="time"
/>import { parseTime } from "@internationalized/date";
<TimeField
className="w-[256px]"
granularity="minute"
maxValue={parseTime("18:00")}
minValue={parseTime("09:00")}
name="time"
>
<Label>Time</Label>
<DateInputGroup>
<DateInputGroup.Input>
{(segment) => <DateInputGroup.Segment segment={segment} />}
</DateInputGroup.Input>
</DateInputGroup>
</TimeField>Start / End 内容
<TimeInput
endContent={<ClockIcon />}
label="Time"
name="time"
startContent={<ClockIcon />}
/><TimeField className="w-[256px]" name="time">
<Label>Time</Label>
<DateInputGroup>
<DateInputGroup.Prefix>
<ClockIcon />
</DateInputGroup.Prefix>
<DateInputGroup.Input>
{(segment) => <DateInputGroup.Segment segment={segment} />}
</DateInputGroup.Input>
<DateInputGroup.Suffix>
<ClockIcon />
</DateInputGroup.Suffix>
</DateInputGroup>
</TimeField>组件结构
v3 TimeField 遵循以下结构:
TimeField (Root)
├── Label (optional)
├── DateInputGroup
│ ├── DateInputGroup.Prefix (optional)
│ ├── DateInputGroup.Input → (segment) => DateInputGroup.Segment
│ └── DateInputGroup.Suffix (optional)
├── Description (optional)
└── FieldError (optional)总结
- 组件重命名:
TimeInput→TimeField - 组件结构:必须使用复合组件:
TimeField(根)配合DateInputGroup与DateInputGroup.Input(render prop)+DateInputGroup.Segment - 标签 / 描述 / 错误:改用独立组件(
Label、Description、FieldError) - 时间相关 prop 不变:
value、defaultValue、onChange、minValue、maxValue、granularity、placeholderValue、isRequired、isDisabled、isInvalid、name、validationBehavior、shouldForceLeadingZeros继续保留在TimeField上 - DateInputGroup 的变体:v3 仅支持
DateInputGroup上的variant="primary"与variant="secondary";color、size、radius已移除——请改用 Tailwind CSS - Start / End 内容:
startContent/endContent→DateInputGroup.Prefix与DateInputGroup.Suffix - 移除 labelPlacement:
labelPlacement已移除——请通过布局自行实现 - DOM / className prop:
groupProps、labelProps、fieldProps、classNames已移除——请在相关部分使用className(以及标准 DOM 属性)