Fixing the Shadcn UI Calendar Break: Seamless Integration with React Day Picker v9
Transitioning to the latest version of your favorite library should be an upgrade, not a headache. However, if you've recently updated to React Day Picker v9, you might have noticed your Shadcn UI Calendar component looking a bit... unconventional.
The Conflict
The release of react-day-picker v9 introduced fundamental changes to its internal DOM structure and class mappings. The standard Shadcn UI implementation, which relies on specific class hooks for layout (like navigation positioning and month grids), doesn't natively translate to these new patterns. The result is often a broken layout where navigation buttons are misaligned and the grid headers are pushed out of place.

The Solution: A Refactored Component
To restore the premium developer experience and visual consistency of your forms and date pickers, we need to update the Calendar component to align with the v9 API.
Update your components/ui/calendar.tsx with the implementation below. This version re-maps the necessary classes to ensure the layout remains robust and visually stunning.
"use client";
import * as React from "react";
import { ChevronLeft, ChevronRight } from "lucide-react";
import { DayPicker } from "react-day-picker";
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={{
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",
caption_label: "text-sm font-medium",
nav: "flex items-center justify-between absolute inset-x-0",
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"),
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 rounded-l-none",
range_start: "day-range-start rounded-r-none",
range_middle: "aria-selected:bg-accent dark:bg-accent/40 rounded-none aria-selected:text-accent-foreground",
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 dark:bg-accent/20",
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",
hidden: "invisible",
...classNames,
}}
components={{
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 };
The Result
With these changes implemented, your calendar will regain its structured, premium look, fully compatible with the new v9 engine.

Dependency Sync
Finally, ensure your project is pinned to a compatible version of the library to maintain stability:
# Update your dependency
npm install react-day-picker@^9.0.0
Conclusion
By aligning your Shadcn UI components with the underlying library updates, you maintain a codebase that is both cutting-edge and reliable. This small adjustment ensures your users continue to experience the sleek, functional interfaces they expect.
Happy coding! 🚀