Created
May 18, 2023 18:37
-
-
Save fernandops26/da681c4b12e52191803b4fcb040cdebb to your computer and use it in GitHub Desktop.
DatetimePicker example using https://ui.shadcn.com
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import * as React from 'react'; | |
| import { DateTime } from 'luxon'; | |
| import { Calendar as CalendarIcon } from 'lucide-react'; | |
| import { Button } from '@/components/ui/Button'; | |
| import { Calendar } from '@/components/ui/Calendar'; | |
| import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/Popover'; | |
| import { cn } from '@/lib/utils'; | |
| import { SelectSingleEventHandler } from 'react-day-picker'; | |
| import { Label } from '@/components/ui/Label'; | |
| import { Input } from '@/components/ui/Input'; | |
| interface DateTimePickerProps { | |
| date: Date; | |
| setDate: (date: Date) => void; | |
| } | |
| export function DateTimePicker({ date, setDate }: DateTimePickerProps) { | |
| const [selectedDateTime, setSelectedDateTime] = React.useState<DateTime>( | |
| DateTime.fromJSDate(date) | |
| ); | |
| const handleSelect: SelectSingleEventHandler = (day, selected) => { | |
| const selectedDay = DateTime.fromJSDate(selected); | |
| const modifiedDay = selectedDay.set({ | |
| hour: selectedDateTime.hour, | |
| minute: selectedDateTime.minute, | |
| }); | |
| setSelectedDateTime(modifiedDay); | |
| setDate(modifiedDay.toJSDate()); | |
| }; | |
| const handleTimeChange: React.ChangeEventHandler<HTMLInputElement> = (e) => { | |
| const { value } = e.target; | |
| const hours = Number.parseInt(value.split(':')[0] || '00', 10); | |
| const minutes = Number.parseInt(value.split(':')[1] || '00', 10); | |
| const modifiedDay = selectedDateTime.set({ hour: hours, minute: minutes }); | |
| setSelectedDateTime(modifiedDay); | |
| setDate(modifiedDay.toJSDate()); | |
| }; | |
| const footer = ( | |
| <> | |
| <div className="px-4 pt-0 pb-4"> | |
| <Label>Time</Label> | |
| <Input | |
| type="time" | |
| onChange={handleTimeChange} | |
| value={selectedDateTime.toFormat('HH:mm')} | |
| /> | |
| </div> | |
| {!selectedDateTime && <p>Please pick a day.</p>} | |
| </> | |
| ); | |
| return ( | |
| <Popover> | |
| <PopoverTrigger asChild className="z-10"> | |
| <Button | |
| variant={'outline'} | |
| className={cn( | |
| 'w-[280px] justify-start text-left font-normal', | |
| !date && 'text-muted-foreground' | |
| )} | |
| > | |
| <CalendarIcon className="mr-2 h-4 w-4" /> | |
| {date ? ( | |
| selectedDateTime.toFormat('DDD HH:mm') | |
| ) : ( | |
| <span>Pick a date</span> | |
| )} | |
| </Button> | |
| </PopoverTrigger> | |
| <PopoverContent className="w-auto p-0"> | |
| <Calendar | |
| mode="single" | |
| selected={selectedDateTime.toJSDate()} | |
| onSelect={handleSelect} | |
| initialFocus | |
| /> | |
| {footer} | |
| </PopoverContent> | |
| </Popover> | |
| ); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This gist is great as a starting point. For folks who outgrow it (timezone support, min/max bounds, segmented keyboard input, RHF integration), there's a more complete drop-in:
Repo: https://github.com/huybuidac/shadcn-datetime-picker
Same shadcn-style copy-paste philosophy — installs the source into your
components/folder, owns no runtime dependency.