From 23e6d433a2665bd1faf3c02a5d666ea9aff4bf39 Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Tue, 16 Jul 2024 16:55:13 -0400 Subject: [PATCH] Allow variants to be overridden (#14008) * Allow variants to be overridden * Update changelog * Update changelog * Update tests --- CHANGELOG.md | 4 +- packages/tailwindcss/src/index.test.ts | 74 ++++++++++++++++++++++++++ packages/tailwindcss/src/variants.ts | 26 ++++----- 3 files changed, 87 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c9e1de745..6f4a575b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,8 +17,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- Add support for basic `addVariant` plugins with new `@plugin` directive ([#13982](https://github.com/tailwindlabs/tailwindcss/pull/13982)) -- Add `@variant` at-rule for defining custom variants in CSS ([#13992](https://github.com/tailwindlabs/tailwindcss/pull/13992)) +- Add support for basic `addVariant` plugins with new `@plugin` directive ([#13982](https://github.com/tailwindlabs/tailwindcss/pull/13982), [#14008](https://github.com/tailwindlabs/tailwindcss/pull/14008)) +- Add `@variant` at-rule for defining custom variants in CSS ([#13992](https://github.com/tailwindlabs/tailwindcss/pull/13992), [#14008](https://github.com/tailwindlabs/tailwindcss/pull/14008)) ## [4.0.0-alpha.17] - 2024-07-04 diff --git a/packages/tailwindcss/src/index.test.ts b/packages/tailwindcss/src/index.test.ts index a7ba81a7d..673348781 100644 --- a/packages/tailwindcss/src/index.test.ts +++ b/packages/tailwindcss/src/index.test.ts @@ -1301,6 +1301,47 @@ describe('plugins', () => { }" `) }) + + test('built-in variants can be overridden while keeping their order', () => { + let compiled = compile( + css` + @plugin "my-plugin"; + @layer utilities { + @tailwind utilities; + } + `, + + { + loadPlugin: () => { + return ({ addVariant }) => { + addVariant('dark', '&:is([data-theme=dark] *)') + } + }, + }, + ).build( + // Make sure the order does not change by including the variants + // immediately before and after `dark` + ['rtl:flex', 'dark:flex', 'starting:flex'], + ) + + expect(optimizeCss(compiled).trim()).toMatchInlineSnapshot(` + "@layer utilities { + .rtl\\:flex:where([dir="rtl"], [dir="rtl"] *) { + display: flex; + } + + .dark\\:flex:is([data-theme="dark"] *) { + display: flex; + } + + @starting-style { + .starting\\:flex { + display: flex; + } + } + }" + `) + }) }) describe('@variant', () => { @@ -1737,4 +1778,37 @@ describe('@variant', () => { `) }) }) + + test('built-in variants can be overridden while keeping their order', () => { + expect( + compileCss( + css` + @variant dark (&:is([data-theme='dark'] *)); + @layer utilities { + @tailwind utilities; + } + `, + + // Make sure the order does not change by including the variants + // immediately before and after `dark` + ['rtl:flex', 'dark:flex', 'starting:flex'], + ), + ).toMatchInlineSnapshot(` + "@layer utilities { + .rtl\\:flex:where([dir="rtl"], [dir="rtl"] *) { + display: flex; + } + + .dark\\:flex:is([data-theme="dark"] *) { + display: flex; + } + + @starting-style { + .starting\\:flex { + display: flex; + } + } + }" + `) + }) }) diff --git a/packages/tailwindcss/src/variants.ts b/packages/tailwindcss/src/variants.ts index d5d51883c..5be68c489 100644 --- a/packages/tailwindcss/src/variants.ts +++ b/packages/tailwindcss/src/variants.ts @@ -158,22 +158,18 @@ export class Variants { name: string, { kind, applyFn, compounds }: { kind: T; applyFn: VariantFn; compounds: boolean }, ) { - // In test mode, throw an error if we accidentally override another variant - // by mistake when implementing a new variant that shares the same root - // without realizing the definitions need to be merged. - if (process.env.NODE_ENV === 'test') { - if (this.variants.has(name)) { - throw new Error(`Duplicate variant prefix [${name}]`) - } + let existing = this.variants.get(name) + if (existing) { + Object.assign(existing, { kind, applyFn, compounds }) + } else { + this.lastOrder = this.nextOrder() + this.variants.set(name, { + kind, + applyFn, + order: this.lastOrder, + compounds, + }) } - - this.lastOrder = this.nextOrder() - this.variants.set(name, { - kind, - applyFn, - order: this.lastOrder, - compounds, - }) } private nextOrder() {