- Alert
- Avatar
- Badge
- Breadcrumb
- Button
- Button Group
- Calendar
- Card
- Carousel
- Chart
- Checkbox
- Checkbox Group
- ComboBox
- Command
- Data Table
- Date Field
- Date Picker
- Date Range Picker
- Dialog
- Disclosure
- Disclosure Group
- Drawer
- Empty
- Field
- File Trigger
- Form
- Grid List
- Hover Card
- Input
- Input Group
- Input OTP
- Item
- Kbd
- Label
- ListBox
- Menu
- Number Field
- Pagination
- Popover
- Progress Bar
- Radio Group
- Range Calendar
- Resizable
- Search Field
- Select
- Separator
- Sheet
- Sidebar
- Skeleton
- Slider
- Sonner
- Spinner
- Switch
- Table
- Tabs
- Tag Group
- Text Field
- Textarea
- Time Field
- Toast
- Toggle Button
- Toggle Button Group
- Tooltip
- Tree
- Typography
import { TimeField } from "@/components/ui/time-field"
export function TimeFieldDemo() {
return <TimeField label="Event time" />
}
Installation
pnpmnpmyarnbunpnpm dlx shadcn@latest add time-field
Usage
import { TimeField } from "@/components/ui/time-field"<TimeField
label="Event time"
description="Select a time for your event."
/>About
The TimeField component is built on top of React Aria Components and uses the @internationalized/date library for time manipulation and formatting.
Examples
Default
import { TimeField } from "@/components/ui/time-field"
export function TimeFieldDemo() {
return <TimeField label="Event time" />
}
<TimeField label="Event time" />With Description
import { TimeField } from "@/components/ui/time-field"
export function TimeFieldDescriptionDemo() {
return (
<TimeField
label="Meeting time"
description="Enter the time for your meeting."
/>
)
}
<TimeField
label="Meeting time"
description="Enter the time for your meeting."
/>Disabled
import { TimeField } from "@/components/ui/time-field"
export function TimeFieldDisabledDemo() {
return <TimeField label="Event time" isDisabled />
}
<TimeField label="Event time" isDisabled />Granularity
import { TimeField } from "@/components/ui/time-field"
export function TimeFieldGranularityDemo() {
return (
<div className="flex flex-col gap-4">
<TimeField label="Hour and minute" granularity="minute" />
<TimeField label="Hour, minute, and second" granularity="second" />
</div>
)
}
<div className="flex flex-col gap-4">
<TimeField label="Hour and minute" granularity="minute" />
<TimeField label="Hour, minute, and second" granularity="second" />
</div>The granularity prop determines which time segments are displayed:
hour- Only hour segmentminute- Hour and minute segments (default)second- Hour, minute, and second segments
Hour Cycle
import { TimeField } from "@/components/ui/time-field"
export function TimeFieldHourCycleDemo() {
return (
<div className="flex flex-col gap-4">
<TimeField label="12-hour format" hourCycle={12} />
<TimeField label="24-hour format" hourCycle={24} />
</div>
)
}
<div className="flex flex-col gap-4">
<TimeField label="12-hour format" hourCycle={12} />
<TimeField label="24-hour format" hourCycle={24} />
</div>The hourCycle prop controls whether the time field uses 12-hour or 24-hour format:
12- 12-hour format with AM/PM24- 24-hour format
Validation
"use client"
import { useState } from "react"
import { Time } from "@internationalized/date"
import { Button } from "@/components/ui/button"
import { TimeField } from "@/components/ui/time-field"
export function TimeFieldValidationDemo() {
const [time, setTime] = useState<Time | null>(null)
return (
<form
className="flex flex-col gap-4"
onSubmit={(e) => {
e.preventDefault()
alert(`Time submitted: ${time?.toString()}`)
}}
>
<TimeField
label="Meeting time"
description="Select a time between 9 AM and 5 PM."
isRequired
value={time}
onChange={setTime}
minValue={new Time(9)}
maxValue={new Time(17)}
errorMessage="Please select a time between 9 AM and 5 PM."
/>
<Button type="submit" className="w-fit">
Submit
</Button>
</form>
)
}
"use client"
import { useState } from "react"
import { Time } from "@internationalized/date"
import { Button } from "@/components/ui/button"
import { TimeField } from "@/components/ui/time-field"
export default function TimeFieldValidation() {
const [time, setTime] = useState<Time | null>(null)
return (
<form
className="flex flex-col gap-4"
onSubmit={(e) => {
e.preventDefault()
alert(`Time submitted: ${time?.toString()}`)
}}
>
<TimeField
label="Meeting time"
description="Select a time between 9 AM and 5 PM."
isRequired
value={time}
onChange={setTime}
minValue={new Time(9)}
maxValue={new Time(17)}
errorMessage="Please select a time between 9 AM and 5 PM."
/>
<Button type="submit" className="w-fit">
Submit
</Button>
</form>
)
}Controlled
Selected time: 09:00:00
"use client"
import { useState } from "react"
import { Time } from "@internationalized/date"
import { TimeField } from "@/components/ui/time-field"
export function TimeFieldControlledDemo() {
const [time, setTime] = useState(new Time(9, 0))
return (
<div className="flex flex-col gap-4">
<TimeField label="Appointment time" value={time} onChange={setTime} />
<p className="text-muted-foreground text-sm">
Selected time: {time.toString()}
</p>
</div>
)
}
"use client"
import { useState } from "react"
import { Time } from "@internationalized/date"
import { TimeField } from "@/components/ui/time-field"
export default function TimeFieldControlled() {
const [time, setTime] = useState(new Time(9, 0))
return (
<div className="flex flex-col gap-4">
<TimeField label="Appointment time" value={time} onChange={setTime} />
<p className="text-sm text-muted-foreground">
Selected time: {time.toString()}
</p>
</div>
)
}API Reference
TimeField
| Prop | Type | Default | Description |
|---|---|---|---|
label | string | - | Label text for the time field |
description | string | - | Help text displayed below the input |
errorMessage | string | ((validation: ValidationResult) => string) | - | Error message for validation |
value | TimeValue | - | The current value (controlled) |
defaultValue | TimeValue | - | The default value (uncontrolled) |
onChange | (value: TimeValue) => void | - | Handler called when the value changes |
minValue | TimeValue | - | The minimum allowed time |
maxValue | TimeValue | - | The maximum allowed time |
granularity | "hour" | "minute" | "second" | "minute" | Determines the smallest unit editable |
hourCycle | 12 | 24 | - | Whether to use 12 or 24 hour time |
isDisabled | boolean | false | Whether the time field is disabled |
isReadOnly | boolean | false | Whether the time field is read-only |
isRequired | boolean | false | Whether the time field is required |
placeholderValue | TimeValue | - | A placeholder time that controls the default values of segments |
See the React Aria TimeField documentation for more props and detailed information.
Internationalization
The TimeField component automatically formats times based on the user's locale. The @internationalized/date library handles time formatting and localization.
import { Time } from "@internationalized/date"
// Create a time object (24-hour format)
const time = new Time(14, 30) // 2:30 PM
// With seconds
const timeWithSeconds = new Time(14, 30, 45) // 2:30:45 PMTime Zones
The Time type represents a clock time without a date or time zone. For date and time with time zones, use ZonedDateTime:
import { parseZonedDateTime } from "@internationalized/date"
const zonedTime = parseZonedDateTime("2024-12-25T14:30[America/New_York]")See the @internationalized/date documentation for more information on time zones.
Common Use Cases
Business Hours
Restrict time selection to business hours:
import { Time } from "@internationalized/date"
import { TimeField } from "@/components/ui/time-field"
<TimeField
label="Meeting time"
description="Select a time between 9 AM and 5 PM."
minValue={new Time(9)}
maxValue={new Time(17)}
/>Appointment Scheduling
Show time in 30-minute increments by using a controlled component:
"use client"
import { useState } from "react"
import { Time } from "@internationalized/date"
import { TimeField } from "@/components/ui/time-field"
export default function AppointmentTime() {
const [time, setTime] = useState(new Time(9, 0))
const handleChange = (newTime: Time) => {
// Round to nearest 30 minutes
const minutes = Math.round(newTime.minute / 30) * 30
setTime(new Time(newTime.hour, minutes))
}
return (
<TimeField
label="Appointment time"
value={time}
onChange={handleChange}
/>
)
}Related Components
- Date Field - For entering dates
- Date Picker - Combines a date field with a calendar
- Field - For composing accessible form fields