diff --git a/.changeset/proud-terms-help.md b/.changeset/proud-terms-help.md new file mode 100644 index 0000000000..497dc7d9f6 --- /dev/null +++ b/.changeset/proud-terms-help.md @@ -0,0 +1,5 @@ +--- +"@heroui/system-rsc": patch +--- + +override with slots (#5785) diff --git a/packages/core/system-rsc/__tests__/extend-variants.test.tsx b/packages/core/system-rsc/__tests__/extend-variants.test.tsx index 7b139f418c..30f80cfb61 100644 --- a/packages/core/system-rsc/__tests__/extend-variants.test.tsx +++ b/packages/core/system-rsc/__tests__/extend-variants.test.tsx @@ -253,4 +253,75 @@ describe("extendVariants function - with slots", () => { expect(baseEl).toHaveClass("shadow-xs"); expect(headerEl).toHaveClass("rounded-none"); }); + + test("should override base component slots with direct slots option", () => { + const Card2 = extendVariants(Card, { + slots: { + header: "!font-bold !text-lg", + footer: "!bg-red-500", + }, + }); + + const {getByTestId} = render(Card Content); + + const headerEl = getByTestId("header"); + const footerEl = getByTestId("footer"); + + expect(headerEl).toHaveClass("!font-bold"); + expect(headerEl).toHaveClass("!text-lg"); + expect(footerEl).toHaveClass("!bg-red-500"); + }); + + test("should merge direct slots with variant-based slots", () => { + const Card2 = extendVariants(Card, { + slots: { + header: "!font-bold", + }, + variants: { + shadow: { + xl: { + base: "shadow-xl", + }, + }, + }, + defaultVariants: { + shadow: "xl", + }, + }); + + const {getByTestId} = render(Card Content); + + const baseEl = getByTestId("base"); + const headerEl = getByTestId("header"); + + expect(baseEl).toHaveClass("shadow-xl"); + expect(headerEl).toHaveClass("!font-bold"); + }); + + test("direct slots should override variant-based slots for the same slot", () => { + const Card2 = extendVariants(Card, { + slots: { + base: "!bg-blue-500", + }, + variants: { + shadow: { + xl: { + base: "shadow-xl", + }, + }, + }, + defaultVariants: { + shadow: "xl", + }, + }); + + const {getByTestId} = render(Card Content); + + const baseEl = getByTestId("base"); + + // Direct slots should be applied + expect(baseEl).toHaveClass("!bg-blue-500"); + // Variant-based slots should also be applied (they merge) + expect(baseEl).toHaveClass("shadow-xl"); + }); }); diff --git a/packages/core/system-rsc/src/extend-variants.js b/packages/core/system-rsc/src/extend-variants.js index 5bd43f14d8..3a1561853e 100644 --- a/packages/core/system-rsc/src/extend-variants.js +++ b/packages/core/system-rsc/src/extend-variants.js @@ -101,9 +101,12 @@ function getClassNamesWithProps({ } export function extendVariants(BaseComponent, styles = {}, opts = {}) { - const {variants, defaultVariants, compoundVariants} = styles || {}; + const {variants, defaultVariants, compoundVariants, slots: directSlots} = styles || {}; + + const inferredSlots = getSlots(variants); + + const slots = directSlots ? {...inferredSlots, ...directSlots} : inferredSlots; - const slots = getSlots(variants); const hasSlots = typeof slots === "object" && Object.keys(slots).length !== 0; const ForwardedComponent = React.forwardRef((originalProps = {}, ref) => {