ui
ui copied to clipboard
[bug]: Calender UI is messed up after updating to react-day-picker
Describe the bug
Calender component has issue i updated react-day-picker then issue appeared. UI of calender is messed up terible UI.
Look on following image:
I am using NextJs14 and problem version of react-day-picker is ^9.3.0
Another thing i noticed that the dev of react-day-picker has changed something on it like currently i am getting error on
Thanks @shadcn
Affected component/components
Calender Component
How to reproduce
Just update react-day-picker to latest version that is 9.3.0
Codesandbox/StackBlitz link
No response
Logs
No response
System Info
Windows 10
NextJs14
Before submitting
- [X] I've made research efforts and searched the documentation
- [X] I've searched for existing issues
Same issue
@kamami, just downgrade react-day-picker version. Still i am using old version of it. Use version 8.X.X then calender will look good.
@kamami, just downgrade react-day-picker version. Still i am using old version of it. Use version 8.X.X then calender will look good.
I would like to, but I need the new UTC support of react-day-picker v9...
Let me try to fix and if i will fix it then generate PR.
It looks like you have date-fns v4 in your package.json, but this code requires v3.
If you'd prefer to use the latest version, you might consider using an alternative component designed for v4 compatibility and UTC support. https://shadcn-datetime-picker-pro.vercel.app/?path=/story/datetimepicker--timezone https://github.com/huybuidac/shadcn-datetime-picker
There are already 2 or 3 PR's addressing this
Any update please ?
I have fixed it temporary, here the code:
function Calendar({
className,
classNames,
showOutsideDays = true,
...props
}: CalendarProps) {
return (
<DayPicker
showOutsideDays={showOutsideDays}
className={cn('p-3', className)}
classNames={{
months: 'flex flex-col relative',
month_caption: 'flex justify-center h-7 mx-10 relative items-center',
weekdays: 'flex flex-row',
weekday: 'text-muted-foreground w-8 font-normal text-[0.8rem]',
month: 'gap-y-4 overflow-x-hidden w-full',
caption: 'flex justify-center pt-1 relative items-center',
caption_label: 'text-sm font-medium truncate',
button_next: cn(
buttonVariants({
variant: 'outline',
className:
'absolute right-0 h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100',
}),
),
button_previous: cn(
buttonVariants({
variant: 'outline',
className:
'absolute left-0 h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100',
}),
),
nav: 'flex items-start justify-between absolute w-full',
month_grid: 'mt-4',
week: 'flex w-full mt-2',
day: 'p-0 size-8 text-sm flex-1 flex items-center justify-center has-[button]:hover:!bg-accent rounded-md has-[button]:hover:aria-selected:!bg-primary has-[button]:hover:text-accent-foreground has-[button]:hover:aria-selected:text-primary-foreground',
day_button: cn(
buttonVariants({ variant: 'ghost' }),
'size-8 p-0 font-normal transition-none hover:bg-transparent hover:text-inherit aria-selected:opacity-100',
),
range_start: 'day-range-start rounded-s-md',
range_end: 'day-range-end rounded-e-md',
selected:
'bg-primary text-primary-foreground hover:!bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground',
today: 'bg-accent text-accent-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 hover:aria-selected:!bg-accent rounded-none aria-selected:text-accent-foreground hover:aria-selected:text-accent-foreground',
hidden: 'invisible',
...classNames,
}}
components={{
PreviousMonthButton: ({ ...props }) => (
<div>
<ChevronLeft className="h-4 w-4 cursor-pointer" />
</div>
),
NextMonthButton: ({ ...props }) => (
<div>
<ChevronRight className="h-4 w-4 cursor-pointer" />
</div>
),
}}
{...props}
/>
);
}
Calendar.displayName = 'Calendar';
export { Calendar };
And
import React from 'react';
import { format, subMonths, addMonths } from 'date-fns';
import { CalendarIcon, XIcon } from 'lucide-react';
import { cn } from '../../../lib/utils';
import ArrowNarrowLeft from '../Icon/ArrowNarrowLeft';
import ArrowNarrowRight from '../Icon/ArrowNarrowRight';
import { Button } from '../ui/button';
import { Calendar } from '../ui/calendar';
import { Popover, PopoverContent, PopoverTrigger } from '../ui/popover';
export interface DatepickerProps {
title?: string | React.ReactNode;
minDate?: string;
maxDate?: string;
getSelectedDate?: (date: Date) => void;
}
const Datepicker: React.FC<DatepickerProps> = ({
title,
getSelectedDate,
minDate = new Date('11/11/1991'),
maxDate = new Date('11/11/3059'),
}) => {
const [date, setDate] = React.useState<Date | undefined>();
const [isCalendarOpen, setIsCalendarOpen] = React.useState(false);
const [month, setMonth] = React.useState(new Date());
const onSelect = (date: Date | undefined) => {
if (date) {
setDate(date);
getSelectedDate && getSelectedDate(date);
}
};
const onHandleClear = () => {
setIsCalendarOpen(false);
setDate(undefined);
};
const onHandleOpenChangePopover = (isOpen: boolean) => {
setIsCalendarOpen(isOpen);
};
const onClickCancel = () => {
setIsCalendarOpen(false);
setDate(undefined);
};
const onHandleApply = () => {
setIsCalendarOpen(false);
};
const onClickCalendarIcon = () => {
setIsCalendarOpen(true);
};
const handlePrevMonthClick = () => {
setMonth(subMonths(month, 1));
};
const handleNextMonthClick = () => {
setMonth(addMonths(month, 1));
};
return (
<div>
{title && (
<div className="text-[14px] leading-[16px] font-normal text-[#4B5563] mb-[4px]">
{title}
</div>
)}
<div className="flex h-[38px] border border-[#E5E7EB] overflow-hidden rounded-[4px]">
<Popover open={isCalendarOpen} onOpenChange={onHandleOpenChangePopover}>
<PopoverTrigger asChild>
<Button
variant={'outline'}
className={cn(
'w-full h-[38px] justify-between font-normal p-[0px] pl-[12px] overflow-hidden border-none',
!date && 'text-muted-foreground',
)}
>
{date ? (
format(date, 'dd-mm-yyyy')
) : (
<span className="text-[#A9A9A9] text-[14px] leading-[16px]">
DD-MM-YYYY
</span>
)}
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto rounded-none shadow-none p-[0px]">
<div>
<div className="border-b pt-[6px] pl-[12px] pr-[12px]">
<Calendar
month={month}
mode="single"
selected={date}
onSelect={onSelect}
autoFocus
hidden={{
before: new Date(minDate),
after: new Date(maxDate),
}}
components={{
PreviousMonthButton: ({ ...props }) => (
<div onClick={handlePrevMonthClick}>
<ArrowNarrowLeft />
</div>
),
NextMonthButton: ({ ...props }) => (
<div onClick={handleNextMonthClick}>
<ArrowNarrowRight />
</div>
),
}}
/>
</div>
<div className="flex justify-end items-center pt-[18px] pb-[18px] pr-[24px] pl-[24px]">
<Button
onClick={onClickCancel}
variant={'outline'}
className="rounded-8px h-[36px] pr-[20px] pl-[20px] pt-[10px] pb-[10px] text-[14px] leading-[16px] text-[#4B5563] border-[#D1D5DB] border"
>
Cancel
</Button>
<Button
onClick={onHandleApply}
className="ml-[16px] h-[36px] rounded-8px bg-[#007AFF] text-[white] pr-[20px] pl-[20px] pt-[10px] pb-[10px] text-[14px] leading-[16px]"
>
Apply
</Button>
</div>
</div>
</PopoverContent>
</Popover>
<div className="w-[80px] h-full bg-[#F9FAFB] flex justify-center items-center border-l pl-[15px] pr-[15px]">
{date && (
<XIcon
onClick={onHandleClear}
className="h-[20px] mr-[4px] w-[20px] text-[#9CA3AF] cursor-pointer"
/>
)}
<CalendarIcon
onClick={onClickCalendarIcon}
className="h-[20px] ml-[4px] w-[20px] text-[#9CA3AF] cursor-pointer"
/>
</div>
</div>
</div>
);
};
export default Datepicker;
Same issue here with version 9.3.2. I had to fix the components property in Shad CN's calendar but then the styling is all off.
you guys can use sippet provide by Yoon Han here https://github.com/shadcn-ui/ui/issues/1574 or
"use client";
import {
ChevronDownIcon,
ChevronLeftIcon,
ChevronRightIcon,
ChevronUpIcon,
} from "lucide-react";
import * as React from "react";
import { DayFlag, DayPicker, SelectionState, UI } from "react-day-picker";
import { cn } from "@/lib/utils";
import { buttonVariants } from "./button";
export type CalendarProps = React.ComponentProps<typeof DayPicker>;
export const Calendar = ({
className,
classNames,
showOutsideDays = true,
...props
}: CalendarProps) => {
return (
<DayPicker
showOutsideDays={showOutsideDays}
className={cn("p-3", className)}
classNames={{
[UI.Months]: "relative",
[UI.Month]: "space-y-4 ml-0",
[UI.MonthCaption]: "flex justify-center items-center h-7",
[UI.CaptionLabel]: "text-sm font-medium",
[UI.PreviousMonthButton]: cn(
buttonVariants({ variant: "outline" }),
"absolute left-1 top-0 h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100",
),
[UI.NextMonthButton]: cn(
buttonVariants({ variant: "outline" }),
"absolute right-1 top-0 h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100",
),
[UI.MonthGrid]: "w-full border-collapse space-y-1",
[UI.Weekdays]: "flex",
[UI.Weekday]:
"text-muted-foreground rounded-md w-9 font-normal text-[0.8rem]",
[UI.Week]: "flex w-full mt-2",
[UI.Day]:
"h-9 w-9 text-center rounded-md 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",
[UI.DayButton]: cn(
buttonVariants({ variant: "ghost" }),
"h-9 w-9 p-0 font-normal aria-selected:opacity-100 hover:bg-primary hover:text-primary-foreground",
),
[SelectionState.range_end]: "day-range-end",
[SelectionState.selected]:
"bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground",
[SelectionState.range_middle]:
"aria-selected:bg-accent aria-selected:text-accent-foreground",
[DayFlag.today]: "bg-accent text-accent-foreground",
[DayFlag.outside]:
"day-outside text-muted-foreground opacity-50 aria-selected:bg-accent/50 aria-selected:text-muted-foreground aria-selected:opacity-30",
[DayFlag.disabled]: "text-muted-foreground opacity-50",
[DayFlag.hidden]: "invisible",
...classNames,
}}
components={{
Chevron: ({ ...props }) => <Chevron {...props} />,
}}
{...props}
/>
);
};
const Chevron = ({ orientation = "left" }) => {
switch (orientation) {
case "left":
return <ChevronLeftIcon className="h-4 w-4" />;
case "right":
return <ChevronRightIcon className="h-4 w-4" />;
case "up":
return <ChevronUpIcon className="h-4 w-4" />;
case "down":
return <ChevronDownIcon className="h-4 w-4" />;
default:
return null;
}
};
@shadcn i think it would be better if docs are updated with this as it took my whole day today figuring this out. Also please refer the repo where the docs can be updated i am up for it. Thanks
typesafe version:
import { ChevronProps } from "react-day-picker";
import { ChevronDown, ChevronLeft, ChevronRight, ChevronUp } from "lucide-react";
const Chevron = ({ orientation }: ChevronProps) => {
if (orientation === "up") {
return <ChevronUp className="h-4 w-4" />;
}
if (orientation === "down") {
return <ChevronDown className="h-4 w-4" />;
}
if (orientation === "right") {
return <ChevronRight className="h-4 w-4" />;
}
return <ChevronLeft className="h-4 w-4" />;
};
This is a temporary solution:
import { ChevronLeft, ChevronRight } from 'lucide-react';
import * as React from 'react';
import { DayFlag, DayPicker, SelectionState, UI } from 'react-day-picker';
import { buttonVariants } from '@/shared/ui/presentation/components/button';
import { cn } from '@/shared/ui/services/utils';
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 relative sm:flex-row space-y-4 sm:space-x-4 sm:space-y-0',
month: 'space-y-4 ',
month_caption: 'flex justify-center items-center',
caption_label: 'text-sm font-medium',
nav: 'space-x-1 flex items-center',
button_previous: cn(
buttonVariants({ variant: 'outline' }),
'absolute left-9 top-3 h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100',
),
button_next: cn(
buttonVariants({ variant: 'outline' }),
'absolute right-9 top-3 h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100',
),
month_grid: 'w-full border-collapse space-y-1',
weekdays: 'flex',
weekday:
'text-muted-foreground rounded-md w-9 font-normal text-[0.8rem]',
week: 'flex w-full mt-2',
day: 'h-9 w-9 text-center rounded-md 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_button: 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',
today: 'bg-accent text-accent-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,
}} */
classNames={{
[UI.Months]: 'relative',
[UI.Month]: 'space-y-4 ml-0',
[UI.MonthCaption]: 'flex justify-center items-center h-7',
[UI.CaptionLabel]: 'text-sm font-medium',
[UI.PreviousMonthButton]: cn(
buttonVariants({ variant: 'outline' }),
'absolute left-1 top-0 h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100',
),
[UI.NextMonthButton]: cn(
buttonVariants({ variant: 'outline' }),
'absolute right-1 top-0 h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100',
),
[UI.MonthGrid]: 'w-full border-collapse space-y-1',
[UI.Weekdays]: 'flex',
[UI.Weekday]:
'text-muted-foreground rounded-md w-9 font-normal text-[0.8rem]',
[UI.Week]: 'flex w-full mt-2',
[UI.Day]:
'h-9 w-9 text-center rounded-md 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',
[UI.DayButton]: cn(
buttonVariants({ variant: 'ghost' }),
'h-9 w-9 p-0 font-normal aria-selected:opacity-100 hover:bg-primary hover:text-primary-foreground',
),
[SelectionState.range_end]: 'day-range-end',
[SelectionState.selected]:
'bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground',
[SelectionState.range_middle]:
'aria-selected:bg-accent aria-selected:text-accent-foreground',
[DayFlag.today]: 'bg-accent text-accent-foreground',
[DayFlag.outside]:
'day-outside text-muted-foreground opacity-50 aria-selected:bg-accent/50 aria-selected:text-muted-foreground aria-selected:opacity-30',
[DayFlag.disabled]: 'text-muted-foreground opacity-50',
[DayFlag.hidden]: 'invisible',
...classNames,
}}
components={{
// @ts-expect-error https://github.com/shadcn-ui/ui/issues/5799
IconLeft: ({ className, ...props }) => (
<ChevronLeft className={cn('h-4 w-4', className)} {...props} />
),
// @ts-expect-error https://github.com/shadcn-ui/ui/issues/5799
IconRight: ({ className, ...props }) => (
<ChevronRight className={cn('h-4 w-4', className)} {...props} />
),
}}
{...props}
/>
);
}
Calendar.displayName = 'Calendar';
export { Calendar };
Be sure to update the imports.
When will be there an official update of the component?
I am having the same issue. Any update on when an official update will be available?
Just checking in to see if there has been an update. Please do not close this.
same problem here
bump pls fix
Can someone validate that the fix I used:
import * as React from "react"
import { DayPicker } from "react-day-picker"
import { ChevronLeftIcon, ChevronRightIcon } from "@radix-ui/react-icons"
import { cn } from "@/lib/utils"
import { buttonVariants } from "@/components/ui/button"
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",
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-8 font-normal text-[0.8rem]",
row: "flex w-full mt-2",
cell: cn(
"relative p-0 text-center text-sm focus-within:relative focus-within:z-20 [&:has([aria-selected])]:bg-accent [&:has([aria-selected].day-outside)]:bg-accent/50 [&:has([aria-selected].day-range-end)]:rounded-r-md",
props.mode === "range"
? "[&:has(>.day-range-end)]:rounded-r-md [&:has(>.day-range-start)]:rounded-l-md first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md"
: "[&:has([aria-selected])]:rounded-md"
),
day: cn(
buttonVariants({ variant: "ghost" }),
"h-8 w-8 p-0 font-normal aria-selected:opacity-100"
),
day_range_start: "day-range-start",
day_range_end: "day-range-end",
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:
"day-outside text-muted-foreground aria-selected:bg-accent/50 aria-selected:text-muted-foreground",
day_disabled: "text-muted-foreground opacity-50",
day_range_middle:
"aria-selected:bg-accent aria-selected:text-accent-foreground",
day_hidden: "invisible",
...classNames,
}}
components={{
IconLeft: ({ className }) => (
<ChevronLeftIcon className={cn("h-4 w-4", className)} />
),
IconRight: ({ className }) => (
<ChevronRightIcon className={cn("h-4 w-4", className)} />
),
}}
{...props}
/>
)
}
Calendar.displayName = "Calendar"
export { Calendar }
This seems to work for me removing the ...props spread but may not be correct
I can confirm that the issue still occurs in the latest versions of shadcn/react-day-picker looking very similar to the images from July 2024.
The solution by sibteali786 copied below fixed it. With this solution I had no styling issues.
Versions used:
- "react-day-picker": "^9.6.4"
- "date-fns": "^4.1.0"
- @latest shadcn button
Before:
After:
"use client";
import {
ChevronDownIcon,
ChevronLeftIcon,
ChevronRightIcon,
ChevronUpIcon,
} from "lucide-react";
import * as React from "react";
import { DayFlag, DayPicker, SelectionState, UI } from "react-day-picker";
import { cn } from "@/lib/utils";
import { buttonVariants } from "./button";
export type CalendarProps = React.ComponentProps<typeof DayPicker>;
export const Calendar = ({
className,
classNames,
showOutsideDays = true,
...props
}: CalendarProps) => {
return (
<DayPicker
showOutsideDays={showOutsideDays}
className={cn("p-3", className)}
classNames={{
[UI.Months]: "relative",
[UI.Month]: "space-y-4 ml-0",
[UI.MonthCaption]: "flex justify-center items-center h-7",
[UI.CaptionLabel]: "text-sm font-medium",
[UI.PreviousMonthButton]: cn(
buttonVariants({ variant: "outline" }),
"absolute left-1 top-0 h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100",
),
[UI.NextMonthButton]: cn(
buttonVariants({ variant: "outline" }),
"absolute right-1 top-0 h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100",
),
[UI.MonthGrid]: "w-full border-collapse space-y-1",
[UI.Weekdays]: "flex",
[UI.Weekday]:
"text-muted-foreground rounded-md w-9 font-normal text-[0.8rem]",
[UI.Week]: "flex w-full mt-2",
[UI.Day]:
"h-9 w-9 text-center rounded-md 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",
[UI.DayButton]: cn(
buttonVariants({ variant: "ghost" }),
"h-9 w-9 p-0 font-normal aria-selected:opacity-100 hover:bg-primary hover:text-primary-foreground",
),
[SelectionState.range_end]: "day-range-end",
[SelectionState.selected]:
"bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground",
[SelectionState.range_middle]:
"aria-selected:bg-accent aria-selected:text-accent-foreground",
[DayFlag.today]: "bg-accent text-accent-foreground",
[DayFlag.outside]:
"day-outside text-muted-foreground opacity-50 aria-selected:bg-accent/50 aria-selected:text-muted-foreground aria-selected:opacity-30",
[DayFlag.disabled]: "text-muted-foreground opacity-50",
[DayFlag.hidden]: "invisible",
...classNames,
}}
components={{
Chevron: ({ ...props }) => <Chevron {...props} />,
}}
{...props}
/>
);
};
const Chevron = ({ orientation = "left" }) => {
switch (orientation) {
case "left":
return <ChevronLeftIcon className="h-4 w-4" />;
case "right":
return <ChevronRightIcon className="h-4 w-4" />;
case "up":
return <ChevronUpIcon className="h-4 w-4" />;
case "down":
return <ChevronDownIcon className="h-4 w-4" />;
default:
return null;
}
};
"use client";
import { ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, ChevronUpIcon, } from "lucide-react"; import * as React from "react"; import { DayFlag, DayPicker, SelectionState, UI } from "react-day-picker";
import { cn } from "@/lib/utils"; import { buttonVariants } from "./button";
export type CalendarProps = React.ComponentProps<typeof DayPicker>;
export const Calendar = ({ className, classNames, showOutsideDays = true, ...props }: CalendarProps) => { return ( <DayPicker showOutsideDays={showOutsideDays} className={cn("p-3", className)} classNames={{ [UI.Months]: "relative", [UI.Month]: "space-y-4 ml-0", [UI.MonthCaption]: "flex justify-center items-center h-7", [UI.CaptionLabel]: "text-sm font-medium", [UI.PreviousMonthButton]: cn( buttonVariants({ variant: "outline" }), "absolute left-1 top-0 h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100", ), [UI.NextMonthButton]: cn( buttonVariants({ variant: "outline" }), "absolute right-1 top-0 h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100", ), [UI.MonthGrid]: "w-full border-collapse space-y-1", [UI.Weekdays]: "flex", [UI.Weekday]: "text-muted-foreground rounded-md w-9 font-normal text-[0.8rem]", [UI.Week]: "flex w-full mt-2", [UI.Day]: "h-9 w-9 text-center rounded-md 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", [UI.DayButton]: cn( buttonVariants({ variant: "ghost" }), "h-9 w-9 p-0 font-normal aria-selected:opacity-100 hover:bg-primary hover:text-primary-foreground", ), [SelectionState.range_end]: "day-range-end", [SelectionState.selected]: "bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground", [SelectionState.range_middle]: "aria-selected:bg-accent aria-selected:text-accent-foreground", [DayFlag.today]: "bg-accent text-accent-foreground", [DayFlag.outside]: "day-outside text-muted-foreground opacity-50 aria-selected:bg-accent/50 aria-selected:text-muted-foreground aria-selected:opacity-30", [DayFlag.disabled]: "text-muted-foreground opacity-50", [DayFlag.hidden]: "invisible", ...classNames, }} components={{ Chevron: ({ ...props }) => <Chevron {...props} />, }} {...props} /> ); };
const Chevron = ({ orientation = "left" }) => { switch (orientation) { case "left": return <ChevronLeftIcon className="h-4 w-4" />; case "right": return <ChevronRightIcon className="h-4 w-4" />; case "up": return <ChevronUpIcon className="h-4 w-4" />; case "down": return <ChevronDownIcon className="h-4 w-4" />; default: return null; } };
Is the code for "after"? How did you manage to get it?
@liawagner Thank you for sharing the patch code. I’m encountering a new issue with the calendar. When I place the calendar control inside a dialog box, clicking on the calendar popover opens the calendar as expected. However, I’m unable to interact with it—any click on the calendar causes it to close immediately, preventing me from selecting a date. Additionally, the next and previous buttons on the calendar are unresponsive.
I found that setting the dialog box's modal property to false resolves the issue, allowing the calendar to function correctly. However, I want the dialog box to remain modal. Has anyone else experienced this problem? If so, what solutions have you found to make the calendar work properly while keeping the dialog box modal?
@liawagner Thank you for sharing the patch code. I’m encountering a new issue with the calendar. When I place the calendar control inside a dialog box, clicking on the calendar popover opens the calendar as expected. However, I’m unable to interact with it—any click on the calendar causes it to close immediately, preventing me from selecting a date. Additionally, the next and previous buttons on the calendar are unresponsive.
I found that setting the dialog box's modal property to false resolves the issue, allowing the calendar to function correctly. However, I want the dialog box to remain modal. Has anyone else experienced this problem? If so, what solutions have you found to make the calendar work properly while keeping the dialog box modal?
Issue resolved by implementing following.