ProComponents, templates & AI tooling
HeroUI
27.7k

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(根)+ DateInputGroupDateInputGroup.Input(render prop)+ DateInputGroup.Segment;可选地搭配 DateInputGroup.PrefixDateInputGroup.Suffix

3. Prop 变更

v2 propv3 位置说明
label改用 Label 组件
description改用 Description 组件
errorMessage改用 FieldError 组件
valuedefaultValueonChangeTimeField与 React Aria 一致
minValuemaxValuegranularityplaceholderValueTimeField相同
isRequiredisDisabledisReadOnlyisInvalidnameTimeField相同
validationBehaviorshouldForceLeadingZerosTimeField相同
variantDateInputGroup简化为仅 primary | secondary
fullWidthTimeFieldDateInputGroup设置在根或分组上
color已移除(请改用 Tailwind CSS)
size已移除(请改用 Tailwind CSS)
radius已移除(请改用 Tailwind CSS)
labelPlacement通过布局自行处理
startContentDateInputGroup.Prefix改用 Prefix 子组件
endContentDateInputGroup.Suffix改用 Suffix 子组件
classNamesTimeFieldDateInputGroup 各部分上使用 className
groupPropsDateInputGroup 上使用 className 或标准 DOM 属性
labelPropsLabel 上使用 className
fieldPropsDateInputGroup 上使用 className
innerWrapperProps在分组 / 输入相关部分上使用 className
descriptionPropsDescription 上使用 className
errorMessagePropsFieldError 上使用 className
inputRefTimeField / 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)

总结

  1. 组件重命名TimeInputTimeField
  2. 组件结构:必须使用复合组件:TimeField(根)配合 DateInputGroupDateInputGroup.Input(render prop)+ DateInputGroup.Segment
  3. 标签 / 描述 / 错误:改用独立组件(LabelDescriptionFieldError
  4. 时间相关 prop 不变valuedefaultValueonChangeminValuemaxValuegranularityplaceholderValueisRequiredisDisabledisInvalidnamevalidationBehaviorshouldForceLeadingZeros 继续保留在 TimeField
  5. DateInputGroup 的变体:v3 仅支持 DateInputGroup 上的 variant="primary"variant="secondary"colorsizeradius 已移除——请改用 Tailwind CSS
  6. Start / End 内容startContent / endContentDateInputGroup.PrefixDateInputGroup.Suffix
  7. 移除 labelPlacementlabelPlacement 已移除——请通过布局自行实现
  8. DOM / className propgroupPropslabelPropsfieldPropsclassNames 已移除——请在相关部分使用 className(以及标准 DOM 属性)

本页目录