TimeInput
Migration guide for TimeInput to TimeField from HeroUI v2 to v3
Refer to the v3 TimeField documentation for complete API reference, styling guide, and advanced examples. This guide only focuses on migrating from HeroUI v2.
Structure Changes
In v2, TimeInput was a single component with props:
import { TimeInput } from "@heroui/react";
export default function App() {
return <TimeInput label="Time" name="time" />;
}
In v3, TimeField requires compound components with DateInputGroup and a render prop for segments:
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>
);
}
Key Changes
1. Component Naming
v2: TimeInput
v3: TimeField
2. Component Structure
v2: Single component with props
v3: Compound components: TimeField (root) + DateInputGroup with DateInputGroup.Input (render prop) and DateInputGroup.Segment; optionally DateInputGroup.Prefix and DateInputGroup.Suffix
3. Prop Changes
| v2 Prop | v3 Location | Notes |
|---|---|---|
label | — | Use Label component |
description | — | Use Description component |
errorMessage | — | Use FieldError component |
value, defaultValue, onChange | TimeField | Same (React Aria) |
minValue, maxValue, granularity, placeholderValue | TimeField | Same |
isRequired, isDisabled, isReadOnly, isInvalid, name | TimeField | Same |
validationBehavior, shouldForceLeadingZeros | TimeField | Same |
variant | DateInputGroup | Simplified to primary | secondary only |
fullWidth | TimeField or DateInputGroup | On root or group |
color | — | Removed (use Tailwind CSS) |
size | — | Removed (use Tailwind CSS) |
radius | — | Removed (use Tailwind CSS) |
labelPlacement | — | Handle with layout |
startContent | DateInputGroup.Prefix | Use Prefix child |
endContent | DateInputGroup.Suffix | Use Suffix child |
classNames | — | Use className on TimeField and DateInputGroup parts |
groupProps | — | Use className or DOM props on DateInputGroup |
labelProps | — | Use className on Label |
fieldProps | — | Use className on DateInputGroup |
innerWrapperProps | — | Use className on group/input parts |
descriptionProps | — | Use className on Description |
errorMessageProps | — | Use className on FieldError |
inputRef | — | Ref handled by TimeField / React Aria |
Migration Examples
With Description and Error
v2
```tsx
<TimeInput
description="Select start time"
label="Start time"
name="startTime"
/>
<TimeInput
errorMessage="Please enter a valid time"
isInvalid
label="Time"
name="time"
/>
```
v3
```tsx
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>
```
Controlled
v2
```tsx
import { parseTime } from "@internationalized/date";
import { useState } from "react";
const [value, setValue] = useState(null);
<TimeInput
label="Time"
name="time"
value={value}
onChange={setValue}
/>
```
v3
```tsx
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>
```
Min/Max and Granularity
v2
```tsx
import { parseTime } from "@internationalized/date";
<TimeInput
granularity="minute"
label="Time"
maxValue={parseTime("18:00")}
minValue={parseTime("09:00")}
name="time"
/>
```
v3
```tsx
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 Content
v2
```tsx
<TimeInput
endContent={<ClockIcon />}
label="Time"
name="time"
startContent={<ClockIcon />}
/>
```
v3
```tsx
<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>
```
Component Anatomy
The v3 TimeField follows this structure:
TimeField (Root)
├── Label (optional)
├── DateInputGroup
│ ├── DateInputGroup.Prefix (optional)
│ ├── DateInputGroup.Input → (segment) => DateInputGroup.Segment
│ └── DateInputGroup.Suffix (optional)
├── Description (optional)
└── FieldError (optional)
Summary
- Component Renamed:
TimeInput→TimeField - Component Structure: Must use compound components:
TimeField(root) andDateInputGroupwithDateInputGroup.Input(render prop) andDateInputGroup.Segment - Label/Description/Error: Use separate components (
Label,Description,FieldError) - Time Props Unchanged:
value,defaultValue,onChange,minValue,maxValue,granularity,placeholderValue,isRequired,isDisabled,isInvalid,name,validationBehavior,shouldForceLeadingZerosstay onTimeField - Variant on DateInputGroup: v3 supports only
variant="primary"andvariant="secondary"onDateInputGroup;color,size,radiusremoved — use Tailwind CSS - Start/End Content:
startContent/endContent→DateInputGroup.PrefixandDateInputGroup.Suffix - Label Placement Removed:
labelPlacementremoved — handle with layout - DOM/Class Props:
groupProps,labelProps,fieldProps,classNamesremoved — useclassName(and standard DOM props) on the relevant parts
Local source: vendor/en/react/migration/(components)/timeinput.mdx
Generated from the pinned HeroUI v3 commit with internal links and previews adapted for JGuang.