diff --git a/CHANGELOG.md b/CHANGELOG.md index 783db8b39a73..c6a3f5fb1f18 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Make it possible to use multiple `` placeholders in a single color definition ([#13740](https://github.com/tailwindlabs/tailwindcss/pull/13740)) +- Don't prefix classes in arbitrary values of `has-*`, `group-has-*`, and `peer-has-*` variants ([#13770](https://github.com/tailwindlabs/tailwindcss/pull/13770)) ## [3.4.3] - 2024-03-27 diff --git a/src/corePlugins.js b/src/corePlugins.js index 51675f931906..6046591855f0 100644 --- a/src/corePlugins.js +++ b/src/corePlugins.js @@ -434,23 +434,40 @@ export let variantPlugins = { ) }, - hasVariants: ({ matchVariant }) => { - matchVariant('has', (value) => `&:has(${normalize(value)})`, { values: {} }) + hasVariants: ({ matchVariant, prefix }) => { + matchVariant('has', (value) => `&:has(${normalize(value)})`, { + values: {}, + [INTERNAL_FEATURES]: { + respectPrefix: false, + }, + }) + matchVariant( 'group-has', (value, { modifier }) => modifier - ? `:merge(.group\\/${modifier}):has(${normalize(value)}) &` - : `:merge(.group):has(${normalize(value)}) &`, - { values: {} } + ? `:merge(${prefix('.group')}\\/${modifier}):has(${normalize(value)}) &` + : `:merge(${prefix('.group')}):has(${normalize(value)}) &`, + { + values: {}, + [INTERNAL_FEATURES]: { + respectPrefix: false, + }, + } ) + matchVariant( 'peer-has', (value, { modifier }) => modifier - ? `:merge(.peer\\/${modifier}):has(${normalize(value)}) ~ &` - : `:merge(.peer):has(${normalize(value)}) ~ &`, - { values: {} } + ? `:merge(${prefix('.peer')}\\/${modifier}):has(${normalize(value)}) ~ &` + : `:merge(${prefix('.peer')}):has(${normalize(value)}) ~ &`, + { + values: {}, + [INTERNAL_FEATURES]: { + respectPrefix: false, + }, + } ) }, diff --git a/tests/prefix.test.js b/tests/prefix.test.js index ab580d192145..8a478f71028f 100644 --- a/tests/prefix.test.js +++ b/tests/prefix.test.js @@ -637,3 +637,132 @@ test('does not prefix arbitrary group/peer classes', async () => { } `) }) + +test('does not prefix has-* variants with arbitrary values', async () => { + let config = { + prefix: 'tw-', + content: [ + { + raw: html` +
+
+
+
+
+
+
+
+
+
+ `, + }, + ], + corePlugins: { preflight: false }, + } + + let input = css` + @tailwind utilities; + ` + + const result = await run(input, config) + + expect(result.css).toMatchFormattedCss(css` + .has-\[\.foo\:hover\]\:tw-block:has(.foo:hover) { + display: block; + } + .has-\[figcaption\]\:tw-inline-block:has(figcaption) { + display: inline-block; + } + .has-\[\[data-active\]\]\:tw-inline:has([data-active]) { + display: inline; + } + .has-\[\.active\]\:tw-flex:has(.active), + .has-\[\.foo\]\:tw-flex:has(.foo) { + display: flex; + } + .has-\[\>_\.potato\]\:tw-table:has(> .potato) { + display: table; + } + .has-\[\+_h2\]\:tw-grid:has(+ h2) { + display: grid; + } + .has-\[\>_h1_\+_h2\]\:tw-contents:has(> h1 + h2) { + display: contents; + } + .has-\[h2\]\:has-\[\.banana\]\:tw-hidden:has(.banana):has(h2) { + display: none; + } + `) +}) + +test('does not prefix group-has-* variants with arbitrary values', () => { + let config = { + prefix: 'tw-', + theme: {}, + content: [ + { + raw: html` +
+
+
+
+
+
+ `, + }, + ], + corePlugins: { preflight: false }, + } + + let input = css` + @tailwind utilities; + ` + + return run(input, config).then((result) => { + expect(result.css).toMatchFormattedCss(css` + .tw-group:has(> h1 + .foo) .group-has-\[\>_h1_\+_\.foo\]\:tw-block { + display: block; + } + .tw-group\/two:has(> h1 + .foo) .group-has-\[\>_h1_\+_\.foo\]\/two\:tw-flex { + display: flex; + } + `) + }) +}) + +test('does not prefix peer-has-* variants with arbitrary values', () => { + let config = { + prefix: 'tw-', + theme: {}, + content: [ + { + raw: html` +
+
+
+
+
+
+
+
+ `, + }, + ], + corePlugins: { preflight: false }, + } + + let input = css` + @tailwind utilities; + ` + + return run(input, config).then((result) => { + expect(result.css).toMatchFormattedCss(css` + .tw-peer:has(> h1 + .foo) ~ .peer-has-\[\>_h1_\+_\.foo\]\:tw-block { + display: block; + } + .tw-peer\/two:has(> h1 + .foo) ~ .peer-has-\[\>_h1_\+_\.foo\]\/two\:tw-flex { + display: flex; + } + `) + }) +})