Time Picker
A flexible time picker component with 12-hour format, AM/PM selection, and optional current time button, designed for easy time selection in forms and applications.
function BasicTimePickerExample() {
const [time, setTime] = React.useState<string>();
return <TimePicker value={time} onChange={setTime} />;
}
Installation
Install following dependencies:
npm install lucide-react
Copy and paste the following code into your project.
"use client";
import * as React from "react";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { Button } from "./button";
export interface TimePickerProps {
value?: string;
onChange?: (value: string) => void;
disabled?: boolean;
error?: boolean;
className?: string;
showCurrentTimeButton?: boolean;
}
export const TimePicker: React.FC<TimePickerProps> = ({
value,
onChange,
disabled,
error,
className,
showCurrentTimeButton = true,
}) => {
const getDefaultTime = React.useCallback(() => {
const now = new Date();
let h = now.getHours();
const m = now.getMinutes();
const ap = h >= 12 ? "PM" : "AM";
h = h % 12;
if (h === 0) h = 12;
return {
hour: String(h).padStart(2, "0"),
minute: String(m).padStart(2, "0"),
amPm: ap,
};
}, []);
const [hour, setHour] = React.useState<string>("");
const [minute, setMinute] = React.useState<string>("");
const [amPm, setAmPm] = React.useState<string>("AM");
const handleSetCurrentTime = React.useCallback(() => {
const def = getDefaultTime();
setHour(def.hour);
setMinute(def.minute);
setAmPm(def.amPm);
if (onChange) {
const newValue = `${def.hour}:${def.minute} ${def.amPm}`;
onChange(newValue);
}
}, [getDefaultTime, onChange]);
React.useEffect(() => {
if (!value) {
const def = getDefaultTime();
setHour(def.hour);
setMinute(def.minute);
setAmPm(def.amPm);
if (onChange) {
const newValue = `${def.hour}:${def.minute} ${def.amPm}`;
onChange(newValue);
}
} else if (
typeof value === "string" &&
value.match(/^\d{1,2}:\d{2} (AM|PM)$/)
) {
const [hm, ap] = value.split(" ");
const [h, m] = hm.split(":");
setHour(h);
setMinute(m);
setAmPm(ap);
}
}, []);
const handleChange = React.useCallback(
(h: string, m: string, ap: string) => {
setHour(h);
setMinute(m);
setAmPm(ap);
if (h && m && ap && onChange) {
const newValue = `${h}:${m} ${ap}`;
if (newValue !== value) {
onChange(newValue);
}
}
},
[onChange, value]
);
return (
<div
className={
className ??
"flex w-full flex-col items-center gap-2" +
(error ? "rounded border border-red-500 p-2" : "")
}
>
<div className="flex w-full items-left gap-2 justify-center">
<div className="w-16">
<Select
disabled={disabled}
onValueChange={React.useCallback(
(val: string) => handleChange(val, minute, amPm),
[minute, amPm, handleChange]
)}
value={hour}
>
<SelectTrigger size="sm">
<SelectValue placeholder="HH" />
</SelectTrigger>
<SelectContent>
{Array.from({ length: 12 }, (_, i) =>
String(i + 1).padStart(2, "0")
).map((h) => (
<SelectItem key={h} value={h}>
{h}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
<span>:</span>
<div className="w-16">
<Select
disabled={disabled}
onValueChange={React.useCallback(
(val: string) => handleChange(hour, val, amPm),
[hour, amPm, handleChange]
)}
value={minute}
>
<SelectTrigger size="sm">
<SelectValue placeholder="MM" />
</SelectTrigger>
<SelectContent>
{Array.from({ length: 60 }, (_, i) =>
String(i).padStart(2, "0")
).map((m) => (
<SelectItem key={m} value={m}>
{m}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
<div className="w-16">
<Select
disabled={disabled}
onValueChange={React.useCallback(
(val: string) => handleChange(hour, minute, val),
[hour, minute, handleChange]
)}
value={amPm}
>
<SelectTrigger size="sm">
<SelectValue placeholder="AM/PM" />
</SelectTrigger>
<SelectContent>
<SelectItem value="AM">AM</SelectItem>
<SelectItem value="PM">PM</SelectItem>
</SelectContent>
</Select>
</div>
</div>
{showCurrentTimeButton && (
<Button
variant={"outline"}
size={"sm"}
disabled={disabled}
onClick={handleSetCurrentTime}
>
Set Current Time
</Button>
)}
</div>
);
};
// Example Components for Documentation
export function BasicTimePickerExample() {
const [time, setTime] = React.useState<string>();
return <TimePicker value={time} onChange={setTime} />;
}
export function TimePickerWithoutButtonExample() {
const [time, setTime] = React.useState<string>();
return (
<TimePicker value={time} onChange={setTime} showCurrentTimeButton={false} />
);
}
export function DisabledTimePickerExample() {
const [time, setTime] = React.useState<string>("02:30 PM");
return <TimePicker value={time} onChange={setTime} disabled />;
}
export function ErrorTimePickerExample() {
const [time, setTime] = React.useState<string>();
return <TimePicker value={time} onChange={setTime} error />;
}
export function CustomStyledTimePickerExample() {
const [time, setTime] = React.useState<string>();
return (
<TimePicker
value={time}
onChange={setTime}
className="flex w-full flex-col items-center gap-2 rounded-lg border-2 border-dashed border-primary/50 p-4"
/>
);
}
export function AppointmentTimePickerExample() {
const [appointmentTime, setAppointmentTime] = React.useState<string>();
const handleTimeChange = (time: string) => {
setAppointmentTime(time);
console.log("Appointment scheduled for:", time);
};
return (
<div className="flex flex-col gap-2 items-center justify-center text-center">
<label className="text-sm font-medium">Select Appointment Time</label>
<TimePicker value={appointmentTime} onChange={handleTimeChange} />
{appointmentTime && (
<p className="text-sm text-muted-foreground">
Selected: {appointmentTime}
</p>
)}
</div>
);
}
export function FormTimePickerExample() {
const [formData, setFormData] = React.useState({
startTime: undefined as string | undefined,
endTime: undefined as string | undefined,
});
return (
<div className="flex flex-col gap-4 max-w-sm items-center justify-center text-center">
<div>
<label className="text-sm font-medium">Start Time</label>
<TimePicker
value={formData.startTime}
onChange={(time) =>
setFormData((prev) => ({ ...prev, startTime: time }))
}
/>
</div>
<div>
<label className="text-sm font-medium">End Time</label>
<TimePicker
value={formData.endTime}
onChange={(time) =>
setFormData((prev) => ({ ...prev, endTime: time }))
}
/>
</div>
{formData.startTime && formData.endTime && (
<div className="rounded-md bg-muted p-3 text-sm">
<p>Meeting scheduled:</p>
<p>
{formData.startTime} - {formData.endTime}
</p>
</div>
)}
</div>
);
}
npx hextaui@latest add time-picker
Usage
import { TimePicker } from "@/components/ui/time-picker";
<TimePicker value={selectedTime} onChange={setSelectedTime} />
Examples
Without Current Time Button
function TimePickerWithoutButtonExample() {
const [time, setTime] = React.useState<string>();
return (
<TimePicker
value={time}
onChange={setTime}
showCurrentTimeButton={false}
/>
);
}
Disabled State
function DisabledTimePickerExample() {
const [time, setTime] = React.useState<string>("02:30 PM");
return <TimePicker value={time} onChange={setTime} disabled />;
}
Error State
function ErrorTimePickerExample() {
const [time, setTime] = React.useState<string>();
return <TimePicker value={time} onChange={setTime} error />;
}
Custom Styling
function CustomStyledTimePickerExample() {
const [time, setTime] = React.useState<string>();
return (
<TimePicker
value={time}
onChange={setTime}
className="flex w-full flex-col items-center gap-2 rounded-lg border-2 border-dashed border-primary/50 p-4"
/>
);
}
Appointment Scheduling
Perfect for appointment booking and scheduling systems.
function AppointmentTimePickerExample() {
const [appointmentTime, setAppointmentTime] = React.useState<string>();
const handleTimeChange = (time: string) => {
setAppointmentTime(time);
console.log("Appointment scheduled for:", time);
};
return (
<div className="space-y-2">
<label className="text-sm font-medium">Select Appointment Time</label>
<TimePicker value={appointmentTime} onChange={handleTimeChange} />
{appointmentTime && (
<p className="text-sm text-muted-foreground">
Selected: {appointmentTime}
</p>
)}
</div>
);
}
Form Integration
Great for forms requiring time input like meeting schedulers and event planners.
function FormTimePickerExample() {
const [formData, setFormData] = React.useState({
startTime: undefined as string | undefined,
endTime: undefined as string | undefined,
});
return (
<div className="space-y-4 max-w-sm">
<div>
<label className="text-sm font-medium">Start Time</label>
<TimePicker
value={formData.startTime}
onChange={(time) =>
setFormData((prev) => ({ ...prev, startTime: time }))
}
/>
</div>
<div>
<label className="text-sm font-medium">End Time</label>
<TimePicker
value={formData.endTime}
onChange={(time) =>
setFormData((prev) => ({ ...prev, endTime: time }))
}
/>
</div>
{formData.startTime && formData.endTime && (
<div className="rounded-md bg-muted p-3 text-sm">
<p>Meeting scheduled:</p>
<p>
{formData.startTime} - {formData.endTime}
</p>
</div>
)}
</div>
);
}
API Reference
TimePicker
Prop | Type | Default |
---|---|---|
value? | string | undefined | - |
onChange? | (value: string) => void | - |
disabled? | boolean | false |
error? | boolean | false |
className? | string | - |
showCurrentTimeButton? | boolean | true |
Time Format
The component uses the format HH:MM AM/PM
where:
HH
is the hour (01-12)MM
is the minute (00-59)AM/PM
indicates morning or afternoon
Examples: 09:30 AM
, 02:15 PM
, 11:45 PM
Last updated on
Textarea
Displays a multi-line text input field with enhanced features like clearable functionality, auto-resizing, and Zod validation support.
TimelineNew
A flexible timeline component for displaying chronological events, processes, and workflows with support for different orientations, statuses, and custom content.