Date & Time Picker
ComponentsReactTailwindDate picker dropdown (month calendar with prev/next nav), time picker dropdown (hour/minute columns), and combined date+time modal for mobile-friendly scheduling. Reuses Dropdown popover + Modal primitives.
Date Picker (Dropdown Popover)
Time Picker (Dropdown Popover)
Date + Time Picker (Modal)
Modal pattern fits mobile better — calendar + time side-by-side, explicit confirm step.
1 "use client"; 2 3 import { useState } from "react"; 4 import { Calendar } from "@/shared/ui/calendar"; 5 import { DatePicker } from "@/shared/ui/date-picker"; 6 import { TimePicker, type TimeValue } from "@/shared/ui/time-picker"; 7 import { Modal, ModalHeader, ModalTitle, ModalFooter } from "@/shared/ui/modal"; 8 import { Button } from "@/shared/ui/button"; 9 10 // === Date Picker — dropdown popover (optional minDate/maxDate/format) === 11 function DateExample() { 12 const [date, setDate] = useState<Date | null>(null); 13 return ( 14 <DatePicker 15 value={date} 16 onChange={setDate} 17 placeholder="Pick a date" 18 minDate={new Date()} 19 /> 20 ); 21 } 22 23 // === Time Picker — dropdown popover with hour/minute columns === 24 function TimeExample() { 25 const [time, setTime] = useState<TimeValue | null>(null); 26 return ( 27 <TimePicker value={time} onChange={setTime} placeholder="Pick a time" minuteStep={15} /> 28 ); 29 } 30 31 // === Date + Time Picker — modal pattern (mobile-friendly) === 32 function ScheduleModal({ 33 open, 34 onClose, 35 onConfirm, 36 }: { 37 open: boolean; 38 onClose: () => void; 39 onConfirm: (v: { date: Date | null; time: TimeValue | null }) => void; 40 }) { 41 const [pendingDate, setPendingDate] = useState<Date | null>(null); 42 const [pendingTime, setPendingTime] = useState<TimeValue | null>(null); 43 44 return ( 45 <Modal open={open} onClose={onClose} className="max-w-2xl"> 46 <ModalHeader> 47 <ModalTitle>Schedule event</ModalTitle> 48 </ModalHeader> 49 <div className="flex flex-col gap-4 md:flex-row md:items-start"> 50 <Calendar value={pendingDate} onSelect={setPendingDate} /> 51 <TimePicker value={pendingTime} onChange={setPendingTime} placeholder="Pick a time" /> 52 </div> 53 <ModalFooter> 54 <Button variant="ghost" onClick={onClose}>Cancel</Button> 55 <Button 56 disabled={!pendingDate || !pendingTime} 57 onClick={() => onConfirm({ date: pendingDate, time: pendingTime })} 58 > 59 Confirm 60 </Button> 61 </ModalFooter> 62 </Modal> 63 ); 64 }