From d8f5aa6dba7b526e09811006cf743099ec26372e Mon Sep 17 00:00:00 2001 From: Mark Skelton Date: Sun, 14 Jan 2024 15:55:03 -0600 Subject: [PATCH] fix: treat `undefined` as `false` for boolean variants --- src/__tests__/tv.test.ts | 72 ++++++++++++++++++++++++++++++++++++++++ src/index.js | 9 ++++- 2 files changed, 80 insertions(+), 1 deletion(-) diff --git a/src/__tests__/tv.test.ts b/src/__tests__/tv.test.ts index a2cedcf..93af34e 100644 --- a/src/__tests__/tv.test.ts +++ b/src/__tests__/tv.test.ts @@ -314,6 +314,78 @@ describe("Tailwind Variants (TV) - Default", () => { expect(h1({color: "green", isUnderline: false})).toBe(expectedResult); }); + + test("should support boolean variants", () => { + const h1 = tv({ + base: "text-3xl", + variants: { + bool: { + true: "underline", + false: "truncate", + }, + }, + }); + + expect(h1()).toHaveClass(["text-3xl", "truncate"]); + expect(h1({bool: true})).toHaveClass(["text-3xl", "underline"]); + expect(h1({bool: false})).toHaveClass(["text-3xl", "truncate"]); + expect(h1({bool: undefined})).toHaveClass(["text-3xl", "truncate"]); + }); + + test("should support boolean variants -- default variants", () => { + const h1 = tv({ + base: "text-3xl", + variants: { + bool: { + true: "underline", + false: "truncate", + }, + }, + defaultVariants: { + bool: true, + }, + }); + + expect(h1()).toHaveClass(["text-3xl", "underline"]); + expect(h1({bool: true})).toHaveClass(["text-3xl", "underline"]); + expect(h1({bool: false})).toHaveClass(["text-3xl", "truncate"]); + expect(h1({bool: undefined})).toHaveClass(["text-3xl", "underline"]); + }); + + test("should support boolean variants -- missing false variant", () => { + const h1 = tv({ + base: "text-3xl", + variants: { + bool: { + true: "underline", + }, + }, + }); + + expect(h1()).toHaveClass(["text-3xl"]); + expect(h1({bool: true})).toHaveClass(["text-3xl", "underline"]); + expect(h1({bool: false})).toHaveClass(["text-3xl"]); + expect(h1({bool: undefined})).toHaveClass(["text-3xl"]); + }); + + test("should support boolean variants -- missing false variant -- default variants", () => { + const h1 = tv({ + base: "text-3xl", + variants: { + bool: { + true: "underline", + }, + }, + defaultVariants: { + bool: true, + }, + }); + + expect(h1()).toHaveClass(["text-3xl", "underline"]); + expect(h1({bool: true})).toHaveClass(["text-3xl", "underline"]); + expect(h1({bool: false})).toHaveClass(["text-3xl"]); + expect(h1({bool: undefined})).toHaveClass(["text-3xl", "underline"]); + }); }); describe("Tailwind Variants (TV) - Slots", () => { diff --git a/src/index.js b/src/index.js index 0c90d60..e8a1de9 100644 --- a/src/index.js +++ b/src/index.js @@ -199,7 +199,14 @@ export const tv = (options, configProp) => { } } - const value = variantObj[variantKey] || variantObj[falsyToString(defaultVariantProp)]; + // If there is a variant key and it's not an object (screen variants), + // we use the variant key and ignore the default variant. + const key = + variantKey != null && typeof variantKey != "object" + ? variantKey + : falsyToString(defaultVariantProp); + + const value = variantObj[key] || variantObj["false"]; if ( typeof screenValues === "object" &&