From 42c84360f51b3798b774665b4cc7c754d0879bc3 Mon Sep 17 00:00:00 2001 From: Giampaolo Bellavite Date: Mon, 11 May 2026 10:58:59 +0200 Subject: [PATCH] fix: apply inline styles to component slots (#2995) * fix: apply inline styles to component slots * chore: add changeset for inline styles fix --- .changeset/clean-masks-drop.md | 5 + .../react-day-picker/src/DayPicker.test.tsx | 94 +++++++++++++++++++ packages/react-day-picker/src/DayPicker.tsx | 23 ++++- .../src/components/Chevron.tsx | 11 ++- .../src/components/Dropdown.tsx | 10 +- .../react-day-picker/src/components/Nav.tsx | 5 + 6 files changed, 142 insertions(+), 6 deletions(-) create mode 100644 .changeset/clean-masks-drop.md diff --git a/.changeset/clean-masks-drop.md b/.changeset/clean-masks-drop.md new file mode 100644 index 000000000..9f94847b3 --- /dev/null +++ b/.changeset/clean-masks-drop.md @@ -0,0 +1,5 @@ +--- +"react-day-picker": patch +--- + +fix: apply inline styles to all component slots. diff --git a/packages/react-day-picker/src/DayPicker.test.tsx b/packages/react-day-picker/src/DayPicker.test.tsx index 94061ce09..bc0359837 100644 --- a/packages/react-day-picker/src/DayPicker.test.tsx +++ b/packages/react-day-picker/src/DayPicker.test.tsx @@ -17,6 +17,7 @@ import type { MonthsProps } from "./components/Months"; import { DayPicker } from "./DayPicker"; import { labelMonthDropdown, labelYearDropdown } from "./labels/index.js"; import { ja } from "./locale/ja.js"; +import { UI } from "./UI"; const testId = "test"; const dayPicker = () => screen.getByTestId(testId); @@ -49,6 +50,99 @@ test("apply classnames and style according to props", () => { expect(dayPicker()).toHaveStyle({ color: "rgb(255, 0, 0)" }); }); +describe("when rendering custom inline styles for component slots", () => { + beforeEach(() => { + render( + , + ); + }); + + test("applies the previous button style", () => { + expect(previousButton()).toHaveAttribute( + "style", + "background-color: blue;", + ); + }); + + test("applies the next button style", () => { + expect(nextButton()).toHaveAttribute("style", "background-color: green;"); + }); + + test("applies the chevron style", () => { + expect(document.querySelector(".rdp-chevron")).toHaveAttribute( + "style", + "fill: red;", + ); + }); + + test("applies the caption label style", () => { + expect(document.querySelector(".rdp-caption_label")).toHaveAttribute( + "style", + "color: purple;", + ); + }); +}); + +describe("when rendering custom inline styles for dropdown slots", () => { + beforeEach(() => { + render( + , + ); + }); + + test("applies the dropdown root style", () => { + expect( + screen.getByRole("combobox", { name: labelMonthDropdown() }) + .parentElement, + ).toHaveAttribute("style", "border-color: blue;"); + }); + + test("applies the month dropdown style with the base dropdown style", () => { + expect( + screen.getByRole("combobox", { name: labelMonthDropdown() }), + ).toHaveAttribute("style", "background-color: yellow; color: green;"); + }); + + test("applies the year dropdown style with the base dropdown style", () => { + expect( + screen.getByRole("combobox", { name: labelYearDropdown() }), + ).toHaveAttribute("style", "background-color: yellow; font-weight: 700;"); + }); + + test("applies the dropdown caption label style", () => { + expect( + document.querySelector(".rdp-dropdown_root .rdp-caption_label"), + ).toHaveAttribute("style", "color: purple;"); + }); + + test("applies the dropdown chevron style", () => { + expect( + document.querySelector(".rdp-dropdown_root .rdp-chevron"), + ).toHaveAttribute("style", "fill: red;"); + }); +}); + test("forward aria attributes to the root element", () => { render( { + const dropdownStyle = styles?.[UI.Dropdown]; + const specificDropdownStyle = styles?.[dropdown]; + + if (!dropdownStyle && !specificDropdownStyle) { + return undefined; + } + + return { + ...dropdownStyle, + ...specificDropdownStyle, + }; + }; + const rootElRef = useRef(null); useAnimation(rootElRef, Boolean(props.animate), { classNames, @@ -438,6 +452,7 @@ export function DayPicker(initialProps: DayPickerProps) { @@ -483,7 +499,7 @@ export function DayPicker(initialProps: DayPickerProps) { formatters, dateLib, )} - style={styles?.[UI.Dropdown]} + style={getDropdownStyle(UI.MonthsDropdown)} value={dateLib.getMonth(calendarMonth.date)} /> ) : ( @@ -511,7 +527,7 @@ export function DayPicker(initialProps: DayPickerProps) { dateLib, Boolean(props.reverseYears), )} - style={styles?.[UI.Dropdown]} + style={getDropdownStyle(UI.YearsDropdown)} value={dateLib.getYear(calendarMonth.date)} /> ) : ( @@ -553,6 +569,7 @@ export function DayPicker(initialProps: DayPickerProps) { ) : ( @@ -570,6 +587,7 @@ export function DayPicker(initialProps: DayPickerProps) { diff --git a/packages/react-day-picker/src/components/Chevron.tsx b/packages/react-day-picker/src/components/Chevron.tsx index 716f0dcd8..b2a826b5f 100644 --- a/packages/react-day-picker/src/components/Chevron.tsx +++ b/packages/react-day-picker/src/components/Chevron.tsx @@ -8,6 +8,7 @@ import React from "react"; */ export function Chevron(props: { className?: string; + style?: React.CSSProperties; /** * The size of the chevron. * @@ -19,11 +20,17 @@ export function Chevron(props: { /** The orientation of the chevron. */ orientation?: "up" | "down" | "left" | "right"; }) { - const { size = 24, orientation = "left", className } = props; + const { size = 24, orientation = "left", className, style } = props; return ( // biome-ignore lint/a11y/noSvgWithoutTitle: handled by the parent component - + {orientation === "up" && ( )} diff --git a/packages/react-day-picker/src/components/Dropdown.tsx b/packages/react-day-picker/src/components/Dropdown.tsx index 5e35afaf6..e2ed78bb8 100644 --- a/packages/react-day-picker/src/components/Dropdown.tsx +++ b/packages/react-day-picker/src/components/Dropdown.tsx @@ -25,7 +25,7 @@ export function Dropdown( } & Omit, "children">, ) { const { options, className, ...selectProps } = props; - const { classNames, components } = useDayPicker(); + const { classNames, components, styles } = useDayPicker(); const cssClassSelect = [classNames[UI.Dropdown], className].join(" "); @@ -36,6 +36,7 @@ export function Dropdown( {options?.map(({ value, label, disabled }) => ( @@ -44,12 +45,17 @@ export function Dropdown( ))} - + {selectedOption?.label} diff --git a/packages/react-day-picker/src/components/Nav.tsx b/packages/react-day-picker/src/components/Nav.tsx index 2d79d4359..2811918f4 100644 --- a/packages/react-day-picker/src/components/Nav.tsx +++ b/packages/react-day-picker/src/components/Nav.tsx @@ -36,6 +36,7 @@ export function Nav( const { components, classNames, + styles, labels: { labelPrevious, labelNext }, } = useDayPicker(); @@ -62,6 +63,7 @@ export function Nav(