-
Star
(167)
You must be signed in to star a gist -
Fork
(26)
You must be signed in to fork a gist
-
-
Save mjbalcueva/1fbcb1be9ef68a82c14d778b686a04fa to your computer and use it in GitHub Desktop.
"use client" | |
import * as React from "react" | |
import { buttonVariants } from "@/components/ui/button" | |
import { ScrollArea } from "@/components/ui/scroll-area" | |
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select" | |
import { cn } from "@/lib/utils" | |
import { ChevronLeft, ChevronRight } from "lucide-react" | |
import { DayPicker, DropdownProps } from "react-day-picker" | |
export type CalendarProps = React.ComponentProps<typeof DayPicker> | |
function Calendar({ className, classNames, showOutsideDays = true, ...props }: CalendarProps) { | |
return ( | |
<DayPicker | |
showOutsideDays={showOutsideDays} | |
className={cn("p-3", className)} | |
classNames={{ | |
months: "flex flex-col sm:flex-row space-y-4 sm:space-x-4 sm:space-y-0", | |
month: "space-y-4", | |
caption: "flex justify-center pt-1 relative items-center", | |
caption_label: "text-sm font-medium", | |
caption_dropdowns: "flex justify-center gap-1", | |
nav: "space-x-1 flex items-center", | |
nav_button: cn( | |
buttonVariants({ variant: "outline" }), | |
"h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100" | |
), | |
nav_button_previous: "absolute left-1", | |
nav_button_next: "absolute right-1", | |
table: "w-full border-collapse space-y-1", | |
head_row: "flex", | |
head_cell: "text-muted-foreground rounded-md w-9 font-normal text-[0.8rem]", | |
row: "flex w-full mt-2", | |
cell: "text-center text-sm p-0 relative [&:has([aria-selected])]:bg-accent first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md focus-within:relative focus-within:z-20", | |
day: cn(buttonVariants({ variant: "ghost" }), "h-9 w-9 p-0 font-normal aria-selected:opacity-100"), | |
day_selected: | |
"bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground", | |
day_today: "bg-accent text-accent-foreground", | |
day_outside: "text-muted-foreground opacity-50", | |
day_disabled: "text-muted-foreground opacity-50", | |
day_range_middle: "aria-selected:bg-accent aria-selected:text-accent-foreground", | |
day_hidden: "invisible", | |
...classNames, | |
}} | |
components={{ | |
Dropdown: ({ value, onChange, children, ...props }: DropdownProps) => { | |
const options = React.Children.toArray(children) as React.ReactElement<React.HTMLProps<HTMLOptionElement>>[] | |
const selected = options.find((child) => child.props.value === value) | |
const handleChange = (value: string) => { | |
const changeEvent = { | |
target: { value }, | |
} as React.ChangeEvent<HTMLSelectElement> | |
onChange?.(changeEvent) | |
} | |
return ( | |
<Select | |
value={value?.toString()} | |
onValueChange={(value) => { | |
handleChange(value) | |
}} | |
> | |
<SelectTrigger className="pr-1.5 focus:ring-0"> | |
<SelectValue>{selected?.props?.children}</SelectValue> | |
</SelectTrigger> | |
<SelectContent position="popper"> | |
<ScrollArea className="h-80"> | |
{options.map((option, id: number) => ( | |
<SelectItem key={`${option.props.value}-${id}`} value={option.props.value?.toString() ?? ""}> | |
{option.props.children} | |
</SelectItem> | |
))} | |
</ScrollArea> | |
</SelectContent> | |
</Select> | |
) | |
}, | |
IconLeft: ({ ...props }) => <ChevronLeft className="h-4 w-4" />, | |
IconRight: ({ ...props }) => <ChevronRight className="h-4 w-4" />, | |
}} | |
{...props} | |
/> | |
) | |
} | |
Calendar.displayName = "Calendar" | |
export { Calendar } |
/* add this snippet in your globals.css file */ | |
.rdp-vhidden { | |
@apply hidden; | |
} |
"use client" | |
import * as React from "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 { format } from "date-fns" | |
import { CalendarIcon } from "lucide-react" | |
export function SampleDatePicker() { | |
const [date, setDate] = React.useState<Date>() | |
return ( | |
<Popover> | |
<PopoverTrigger asChild> | |
<Button | |
variant={"outline"} | |
className={cn("w-[240px] justify-start text-left font-normal", !date && "text-muted-foreground")} | |
> | |
<CalendarIcon className="mr-2 h-4 w-4" /> | |
{date ? format(date, "PPP") : <span>Pick a date</span>} | |
</Button> | |
</PopoverTrigger> | |
<PopoverContent align="start" className=" w-auto p-0"> | |
<Calendar | |
mode="single" | |
captionLayout="dropdown-buttons" | |
selected={date} | |
onSelect={setDate} | |
fromYear={1960} | |
toYear={2030} | |
/> | |
</PopoverContent> | |
</Popover> | |
) | |
} |
Is there a version of it, that works with react-day-picker v9?
Thank you!
@Maliksidk19 you mean this
here is mine, see 👁️ the difference.
Is there a version of it, that works with react-day-picker v9?
I have managed to make it work in Next.js 15.1.3, with react 19, shadcn 2.1.8 and react-day-picker 9.5.0
Calendar component call
<PopoverContent className="w-auto p-0" align="start">
<Calendar
mode="single"
captionLayout="dropdown"
selected={field.value ?? new Date()}
onSelect={field.onChange}
endMonth={new Date()}
disabled={{
after: new Date(),
before: new Date(1900, 0),
}}
/>
</PopoverContent>
calendar.tsx
"use client";
import * as React from "react";
import { ChevronLeft, ChevronRight } from "lucide-react";
import { DayPicker, DropdownProps } from "react-day-picker";
import { cn } from "@/lib/utils";
import { buttonVariants } from "@/components/ui/button";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "./select";
import { ScrollArea } from "./scroll-area";
export type CalendarProps = React.ComponentProps<typeof DayPicker>;
function Calendar({
className,
classNames,
showOutsideDays = true,
...props
}: CalendarProps) {
return (
<DayPicker
showOutsideDays={showOutsideDays}
className={cn("p-3", className)}
classNames={{
month: "space-y-4",
months: "flex flex-col sm:flex-row space-y-4 sm:space-y-0 relative",
month_caption: "flex justify-center pt-1 relative items-center",
month_grid: "w-full border-collapse space-y-1",
// TEST
dropdowns: "flex justify-center gap-1",
nav: "flex items-center justify-between absolute inset-x-0 top-2",
button_previous: cn(
buttonVariants({ variant: "outline" }),
"h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100 z-10",
),
button_next: cn(
buttonVariants({ variant: "outline" }),
"h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100 z-10",
),
// TEST
weeks: "w-full border-collapse space-y-",
weekdays: "flex",
weekday:
"text-muted-foreground rounded-md w-9 font-normal text-[0.8rem]",
week: "flex w-full mt-2",
day_button:
"h-9 w-9 text-center text-sm p-0 relative [&:has([aria-selected].day-range-end)]:rounded-r-md [&:has([aria-selected].day-outside)]:bg-accent/50 [&:has([aria-selected])]:bg-accent first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md focus-within:relative focus-within:z-20",
day: cn(
buttonVariants({ variant: "ghost" }),
"h-9 w-9 p-0 font-normal aria-selected:opacity-100",
),
range_end: "day-range-end",
selected:
"bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground",
outside:
"day-outside text-muted-foreground opacity-50 aria-selected:bg-accent/50 aria-selected:text-muted-foreground aria-selected:opacity-30",
disabled: "text-muted-foreground opacity-50",
range_middle:
"aria-selected:bg-accent aria-selected:text-accent-foreground",
hidden: "invisible",
...classNames,
}}
components={{
Dropdown: ({ value, onChange, options }: DropdownProps) => {
const selected = options?.find((child) => child.value === value);
const handleChange = (value: string) => {
const changeEvent = {
target: { value },
} as React.ChangeEvent<HTMLSelectElement>;
onChange?.(changeEvent);
};
return (
<Select
value={value?.toString()}
onValueChange={(value) => {
handleChange(value);
}}
>
<SelectTrigger className="pr-1.5 focus:ring-0">
<SelectValue>{selected?.label}</SelectValue>
</SelectTrigger>
<SelectContent position="popper">
<ScrollArea className="h-80">
{options?.map((option, id: number) => (
<SelectItem
key={`${option.value}-${id}`}
value={option.value?.toString() ?? ""}
>
{option.label}
</SelectItem>
))}
</ScrollArea>
</SelectContent>
</Select>
);
},
Chevron: ({ ...props }) =>
props.orientation === "left" ? (
<ChevronLeft {...props} className="h-4 w-4" />
) : (
<ChevronRight {...props} className="h-4 w-4" />
),
}}
{...props}
/>
);
}
Calendar.displayName = "Calendar";
export { Calendar };
A small change, instead of adding to the CSS file
.rdp-vhidden { @apply hidden; }Apply the Tailwind selector directly in the component declaration:
<DayPicker showOutsideDays={showOutsideDays} className={cn("p-3", className)} classNames={{ months: "flex flex-col sm:flex-row space-y-4 sm:space-x-4 sm:space-y-0", month: "space-y-4", //... vhidden: "vhidden hidden", // Add this line //.. }}
Thank you very much
Is there a version of it, that works with react-day-picker v9?
here you have my version of the calendar with react-day-picker v.9
Is there a version of it, that works with react-day-picker v9?
here you have my version of the calendar with react-day-picker v.9
Thanks a lot! Works perfectly.
I can share you one of a component which works too : https://gist.github.com/maxgfr/94b00cfc2a8bb4031f36e52b0923b56d
Shadcn datetime picker is now updated to work with [email protected], react@19 and [email protected] without any issue
https://shadcn-datetime-picker.vercel.app/datetime-picker
@Mr-Vipi (I have used your react-day-picker v9 calendae component code and changed it a bit) Thanks ✨
Hi thanks for the information issue is fixed I missed defaultMonth prop with the value.
Thank you