diff --git a/src/__tests__/tv.test.ts b/src/__tests__/tv.test.ts index a4ef458..42efa7d 100644 --- a/src/__tests__/tv.test.ts +++ b/src/__tests__/tv.test.ts @@ -691,6 +691,37 @@ describe("Tailwind Variants (TV) - Slots", () => { expectTv(list(), ["list-none", "color--secondary-list", "compound--list"]); expectTv(wrapper(), ["flex", "flex-col", "color--secondary-wrapper", "compound--wrapper"]); }); + + test("should support slot level variant overrides", () => { + const menu = tv({ + base: "text-3xl", + slots: { + title: "text-2xl", + }, + variants: { + color: { + primary: { + base: "color--primary-base", + title: "color--primary-title", + }, + secondary: { + base: "color--secondary-base", + title: "color--secondary-title", + }, + }, + }, + defaultVariants: { + color: "primary", + }, + }); + + const {base, title} = menu(); + + expectTv(base(), ["text-3xl", "color--primary-base"]); + expectTv(title(), ["text-2xl", "color--primary-title"]); + expectTv(base({color: "secondary"}), ["text-3xl", "color--secondary-base"]); + expectTv(title({color: "secondary"}), ["text-2xl", "color--secondary-title"]); + }); }); describe("Tailwind Variants (TV) - Compound Slots", () => { diff --git a/src/index.d.ts b/src/index.d.ts index 55e0a30..6012b50 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -201,8 +201,8 @@ export type TVReturnType< (props?: TVProps): ES extends undefined ? S extends undefined ? string - : {[K in TVSlotsWithBase]: (slotProps?: ClassProp) => string} - : {[K in TVSlotsWithBase]: (slotProps?: ClassProp) => string}; + : {[K in TVSlotsWithBase]: (slotProps?: TVProps) => string} + : {[K in TVSlotsWithBase]: (slotProps?: TVProps) => string}; } & TVReturnProps; export type TV = { diff --git a/src/index.js b/src/index.js index 859745b..fec6d7a 100644 --- a/src/index.js +++ b/src/index.js @@ -139,14 +139,14 @@ export const tv = (options, configProp) => { return result; }; - const getVariantValue = (variant, vrs = variants, slotKey = null) => { + const getVariantValue = (variant, vrs = variants, slotKey = null, slotProps = null) => { const variantObj = vrs?.[variant]; if (!variantObj || isEmptyObject(variantObj)) { return null; } - const variantProp = props?.[variant]; + const variantProp = slotProps?.[variant] ?? props?.[variant]; if (variantProp === null) return null; @@ -204,13 +204,13 @@ export const tv = (options, configProp) => { return Object.keys(variants).map((vk) => getVariantValue(vk, variants)); }; - const getVariantClassNamesBySlotKey = (slotKey) => { + const getVariantClassNamesBySlotKey = (slotKey, slotProps) => { if (!variants || typeof variants !== "object") { return null; } return Object.keys(variants).reduce((acc, variant) => { - const variantValue = getVariantValue(variant, variants, slotKey); + const variantValue = getVariantValue(variant, variants, slotKey, slotProps); const value = slotKey === "base" && typeof variantValue === "string" @@ -333,7 +333,7 @@ export const tv = (options, configProp) => { acc[slotKey] = (slotProps) => cn( slots[slotKey], - getVariantClassNamesBySlotKey(slotKey), + getVariantClassNamesBySlotKey(slotKey, slotProps), compoundClassNames?.[slotKey], compoundSlotClassNames?.[slotKey], slotProps?.class,