From 54a66ed2dabe59a321286f1473491a6c3e293d5a Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 5 Apr 2026 18:47:43 +0000 Subject: [PATCH] Sync calendar from shadcn and fix Tailwind v4.2 CSS var syntax Pulls the latest shadcn `calendar` component to stay in sync with upstream, then patches the CSS custom property references. Tailwind v4 removed the `[--var]` shorthand for referencing CSS custom properties in favor of `(--var)`. shadcn's calendar still ships the v3-style `[--cell-size]` references, so after our Tailwind 4.2.1 bump the nav buttons, month caption, weekday header, and day cells all lost their height/width and the datepicker popover collapsed onto itself and overflowed its container. https://claude.ai/code/session_01BaxphtzayVB1ianzzf7C3x --- components/ui/calendar.tsx | 99 ++++++++++++++++++-------------------- 1 file changed, 48 insertions(+), 51 deletions(-) diff --git a/components/ui/calendar.tsx b/components/ui/calendar.tsx index 3470cf70..a1ea73db 100644 --- a/components/ui/calendar.tsx +++ b/components/ui/calendar.tsx @@ -1,15 +1,15 @@ -"use client"; +"use client" -import * as React from "react"; +import * as React from "react" import { ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, -} from "lucide-react"; -import { DayButton, DayPicker, getDefaultClassNames } from "react-day-picker"; +} from "lucide-react" +import { DayButton, DayPicker, getDefaultClassNames } from "react-day-picker" -import { cn } from "@/lib/utils"; -import { Button, buttonVariants } from "@/components/ui/button"; +import { cn } from "@/lib/utils" +import { Button, buttonVariants } from "@/components/ui/button" function Calendar({ className, @@ -21,9 +21,9 @@ function Calendar({ components, ...props }: React.ComponentProps & { - buttonVariant?: React.ComponentProps["variant"]; + buttonVariant?: React.ComponentProps["variant"] }) { - const defaultClassNames = getDefaultClassNames(); + const defaultClassNames = getDefaultClassNames() return ( svg]:rotate-180`, String.raw`rtl:**:[.rdp-button\_previous>svg]:rotate-180`, - className, + className )} captionLayout={captionLayout} formatters={{ @@ -41,88 +41,85 @@ function Calendar({ ...formatters, }} classNames={{ - root: cn("w-fit min-w-[280px]", defaultClassNames.root), + root: cn("w-fit", defaultClassNames.root), months: cn( "relative flex flex-col gap-4 md:flex-row", - defaultClassNames.months, - ), - month: cn( - "flex w-full min-w-[280px] flex-col gap-4", - defaultClassNames.month, + defaultClassNames.months ), + month: cn("flex w-full flex-col gap-4", defaultClassNames.month), nav: cn( "absolute inset-x-0 top-0 flex w-full items-center justify-between gap-1", - defaultClassNames.nav, + defaultClassNames.nav ), button_previous: cn( buttonVariants({ variant: buttonVariant }), - "h-[--cell-size] w-[--cell-size] select-none p-0 aria-disabled:opacity-50", - defaultClassNames.button_previous, + "h-(--cell-size) w-(--cell-size) select-none p-0 aria-disabled:opacity-50", + defaultClassNames.button_previous ), button_next: cn( buttonVariants({ variant: buttonVariant }), - "h-[--cell-size] w-[--cell-size] select-none p-0 aria-disabled:opacity-50", - defaultClassNames.button_next, + "h-(--cell-size) w-(--cell-size) select-none p-0 aria-disabled:opacity-50", + defaultClassNames.button_next ), month_caption: cn( - "flex h-[--cell-size] w-full items-center justify-center px-[--cell-size]", - defaultClassNames.month_caption, + "flex h-(--cell-size) w-full items-center justify-center px-(--cell-size)", + defaultClassNames.month_caption ), dropdowns: cn( - "flex h-[--cell-size] w-full items-center justify-center gap-1.5 text-sm font-medium", - defaultClassNames.dropdowns, + "flex h-(--cell-size) w-full items-center justify-center gap-1.5 text-sm font-medium", + defaultClassNames.dropdowns ), dropdown_root: cn( "has-focus:border-ring border-input shadow-xs has-focus:ring-ring/50 has-focus:ring-[3px] relative rounded-md border", - defaultClassNames.dropdown_root, + defaultClassNames.dropdown_root ), dropdown: cn( "bg-popover absolute inset-0 opacity-0", - defaultClassNames.dropdown, + defaultClassNames.dropdown ), caption_label: cn( "select-none font-medium", captionLayout === "label" ? "text-sm" : "[&>svg]:text-muted-foreground flex h-8 items-center gap-1 rounded-md pl-2 pr-1 text-sm [&>svg]:size-3.5", - defaultClassNames.caption_label, + defaultClassNames.caption_label ), table: "w-full border-collapse", weekdays: cn("flex", defaultClassNames.weekdays), weekday: cn( "text-muted-foreground flex-1 select-none rounded-md text-[0.8rem] font-normal", - defaultClassNames.weekday, + defaultClassNames.weekday ), week: cn("mt-2 flex w-full", defaultClassNames.week), week_number_header: cn( - "w-[--cell-size] select-none", - defaultClassNames.week_number_header, + "w-(--cell-size) select-none", + defaultClassNames.week_number_header ), week_number: cn( "text-muted-foreground select-none text-[0.8rem]", - defaultClassNames.week_number, + defaultClassNames.week_number ), day: cn( "group/day relative aspect-square h-full w-full select-none p-0 text-center [&:first-child[data-selected=true]_button]:rounded-l-md [&:last-child[data-selected=true]_button]:rounded-r-md", - defaultClassNames.day, + defaultClassNames.day ), range_start: cn( "bg-accent rounded-l-md", - defaultClassNames.range_start, + defaultClassNames.range_start ), range_middle: cn("rounded-none", defaultClassNames.range_middle), range_end: cn("bg-accent rounded-r-md", defaultClassNames.range_end), today: cn( "bg-accent text-accent-foreground rounded-md data-[selected=true]:rounded-none", - defaultClassNames.today, + defaultClassNames.today ), outside: cn( "text-muted-foreground aria-selected:text-muted-foreground", - defaultClassNames.outside, + defaultClassNames.outside ), disabled: cn( "text-muted-foreground opacity-50", - defaultClassNames.disabled, + defaultClassNames.disabled ), hidden: cn("invisible", defaultClassNames.hidden), ...classNames, @@ -136,13 +133,13 @@ function Calendar({ className={cn(className)} {...props} /> - ); + ) }, Chevron: ({ className, orientation, ...props }) => { if (orientation === "left") { return ( - ); + ) } if (orientation === "right") { @@ -151,28 +148,28 @@ function Calendar({ className={cn("size-4", className)} {...props} /> - ); + ) } return ( - ); + ) }, DayButton: CalendarDayButton, WeekNumber: ({ children, ...props }) => { return ( -
+
{children}
- ); + ) }, ...components, }} {...props} /> - ); + ) } function CalendarDayButton({ @@ -181,12 +178,12 @@ function CalendarDayButton({ modifiers, ...props }: React.ComponentProps) { - const defaultClassNames = getDefaultClassNames(); + const defaultClassNames = getDefaultClassNames() - const ref = React.useRef(null); + const ref = React.useRef(null) React.useEffect(() => { - if (modifiers.focused) ref.current?.focus(); - }, [modifiers.focused]); + if (modifiers.focused) ref.current?.focus() + }, [modifiers.focused]) return (