Components
Time Input
Segmented React Aria time field with locale-aware hour, minute, and AM/PM slots aligned to shadcn tokens.
Time Input captures a time-of-day with React Aria segments inside the same bordered shell as the date family. It avoids native <input type="time"> so styling stays on your design tokens and the control works consistently across browsers.
Design guide
- Segmented over native — Prefer this component (or date pickers with
withTime) overtype="time"in product UI. - Locale-first — Hour cycle (12h vs 24h) follows locale unless you set
hourCycle. - Minute by default — Use
granularity="second"only when sub-minute precision matters. - Validate on blur — Partial typing is allowed while focused; commit when the user leaves the field.
- Range + time — Use two Time Inputs (or Date Range Picker
withTime) for start and end; never one shared clock for both ends.
Installing
pnpm dlx shadcn@latest add https://ui.isaacfei.com/r/time-input.jsonUsage
import { useState } from "react";
import { TimeInput } from "@/components/f-ui/time-input/time-input";
export function Example() {
const [time, setTime] = useState<Date>();
return (
<TimeInput
label="Start time"
value={time ?? null}
onChange={setTime}
/>
);
}Embed only the field (no label) via TimeInputControl — used inside calendar range footers:
import { TimeInputControl } from "@/components/f-ui/time-input/time-input";Examples
930AM
Locale-aware segments; use arrow keys to adjust.
"use client";
import { useState } from "react";
import { TimeInput } from "@/components/f-ui/time-input/time-input";
export function TimeInputDemo() {
const [time, setTime] = useState<Date | undefined>(
() => new Date(2026, 4, 21, 9, 30, 0, 0),
);
return (
<div className="max-w-xs w-full">
<TimeInput
label="Meeting time"
value={time ?? null}
onChange={setTime}
description="Locale-aware segments; use arrow keys to adjust."
/>
</div>
);
}API Reference
| Prop | Type | Default |
|---|---|---|
value | Date | null | — |
onChange | (time: Date | undefined) => void | — |
granularity | "minute" | "second" | "minute" |
hourCycle | 12 | 24 | locale |
minValue / maxValue | Date | time-of-day bounds |
disabled | boolean | false |
isInvalid | boolean | false |
label | ReactNode | — |
description / errorMessage | ReactNode | — |
locale | string | i18n provider |
classNames | { root?, input? } | — |
value / onChange use Date for compatibility with date pickers; only the clock portion is read or written (normalized to today in the local timezone).