diff --git a/CHANGELOG.md b/CHANGELOG.md index 196ba911531d..ba224d8ab740 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Ensure instances of the same variant with different values are always sorted deterministically (e.g. `data-focus:flex` and `data-active:flex`) ([#14835](https://github.com/tailwindlabs/tailwindcss/pull/14835)) - Ensure `--inset-ring=*` and `--inset-shadow-*` variables are ignored by `inset-*` utilities ([#14855](https://github.com/tailwindlabs/tailwindcss/pull/14855)) - Ensure `url(…)` containing special characters such as `;` or `{}` end up in one declaration ([#14879](https://github.com/tailwindlabs/tailwindcss/pull/14879)) +- Ensure adjacent rules are merged together after handling nesting when generating optimized CSS ([#14873](https://github.com/tailwindlabs/tailwindcss/pull/14873)) - _Upgrade (experimental)_: Install `@tailwindcss/postcss` next to `tailwindcss` ([#14830](https://github.com/tailwindlabs/tailwindcss/pull/14830)) - _Upgrade (experimental)_: Remove whitespace around `,` separator when print arbitrary values ([#14838](https://github.com/tailwindlabs/tailwindcss/pull/14838)) diff --git a/packages/@tailwindcss-cli/src/commands/build/index.ts b/packages/@tailwindcss-cli/src/commands/build/index.ts index 3a5fd120b81a..d36a3ab7c949 100644 --- a/packages/@tailwindcss-cli/src/commands/build/index.ts +++ b/packages/@tailwindcss-cli/src/commands/build/index.ts @@ -410,22 +410,28 @@ function optimizeCss( input: string, { file = 'input.css', minify = false }: { file?: string; minify?: boolean } = {}, ) { - return transform({ - filename: file, - code: Buffer.from(input), - minify, - sourceMap: false, - drafts: { - customMedia: true, - }, - nonStandard: { - deepSelectorCombinator: true, - }, - include: Features.Nesting, - exclude: Features.LogicalProperties, - targets: { - safari: (16 << 16) | (4 << 8), - }, - errorRecovery: true, - }).code.toString() + function optimize(code: Buffer | Uint8Array) { + return transform({ + filename: file, + code, + minify, + sourceMap: false, + drafts: { + customMedia: true, + }, + nonStandard: { + deepSelectorCombinator: true, + }, + include: Features.Nesting, + exclude: Features.LogicalProperties, + targets: { + safari: (16 << 16) | (4 << 8), + }, + errorRecovery: true, + }).code + } + + // Running Lightning CSS twice to ensure that adjacent rules are merged after + // nesting is applied. This creates a more optimized output. + return optimize(optimize(Buffer.from(input))).toString() } diff --git a/packages/@tailwindcss-postcss/src/__snapshots__/index.test.ts.snap b/packages/@tailwindcss-postcss/src/__snapshots__/index.test.ts.snap index a48e7a689835..5703d8047d2e 100644 --- a/packages/@tailwindcss-postcss/src/__snapshots__/index.test.ts.snap +++ b/packages/@tailwindcss-postcss/src/__snapshots__/index.test.ts.snap @@ -421,6 +421,7 @@ exports[`\`@import 'tailwindcss'\` is replaced with the generated CSS 1`] = ` color: inherit; -webkit-text-decoration: inherit; -webkit-text-decoration: inherit; + -webkit-text-decoration: inherit; text-decoration: inherit; } diff --git a/packages/@tailwindcss-postcss/src/index.ts b/packages/@tailwindcss-postcss/src/index.ts index d9ff2d2db187..f5e3781bfbf0 100644 --- a/packages/@tailwindcss-postcss/src/index.ts +++ b/packages/@tailwindcss-postcss/src/index.ts @@ -218,24 +218,30 @@ function optimizeCss( input: string, { file = 'input.css', minify = false }: { file?: string; minify?: boolean } = {}, ) { - return transform({ - filename: file, - code: Buffer.from(input), - minify, - sourceMap: false, - drafts: { - customMedia: true, - }, - nonStandard: { - deepSelectorCombinator: true, - }, - include: Features.Nesting, - exclude: Features.LogicalProperties, - targets: { - safari: (16 << 16) | (4 << 8), - }, - errorRecovery: true, - }).code.toString() + function optimize(code: Buffer | Uint8Array) { + return transform({ + filename: file, + code, + minify, + sourceMap: false, + drafts: { + customMedia: true, + }, + nonStandard: { + deepSelectorCombinator: true, + }, + include: Features.Nesting, + exclude: Features.LogicalProperties, + targets: { + safari: (16 << 16) | (4 << 8), + }, + errorRecovery: true, + }).code + } + + // Running Lightning CSS twice to ensure that adjacent rules are merged after + // nesting is applied. This creates a more optimized output. + return optimize(optimize(Buffer.from(input))).toString() } export default Object.assign(tailwindcss, { postcss: true }) as PluginCreator diff --git a/packages/@tailwindcss-vite/src/index.ts b/packages/@tailwindcss-vite/src/index.ts index 6442288912a5..4f02e60f290c 100644 --- a/packages/@tailwindcss-vite/src/index.ts +++ b/packages/@tailwindcss-vite/src/index.ts @@ -277,24 +277,30 @@ function optimizeCss( input: string, { file = 'input.css', minify = false }: { file?: string; minify?: boolean } = {}, ) { - return transform({ - filename: file, - code: Buffer.from(input), - minify, - sourceMap: false, - drafts: { - customMedia: true, - }, - nonStandard: { - deepSelectorCombinator: true, - }, - include: Features.Nesting, - exclude: Features.LogicalProperties, - targets: { - safari: (16 << 16) | (4 << 8), - }, - errorRecovery: true, - }).code.toString() + function optimize(code: Buffer | Uint8Array) { + return transform({ + filename: file, + code, + minify, + sourceMap: false, + drafts: { + customMedia: true, + }, + nonStandard: { + deepSelectorCombinator: true, + }, + include: Features.Nesting, + exclude: Features.LogicalProperties, + targets: { + safari: (16 << 16) | (4 << 8), + }, + errorRecovery: true, + }).code + } + + // Running Lightning CSS twice to ensure that adjacent rules are merged after + // nesting is applied. This creates a more optimized output. + return optimize(optimize(Buffer.from(input))).toString() } function idToPath(id: string) { diff --git a/packages/tailwindcss/src/compat/plugin-api.test.ts b/packages/tailwindcss/src/compat/plugin-api.test.ts index c4da90503419..bfe86c89538d 100644 --- a/packages/tailwindcss/src/compat/plugin-api.test.ts +++ b/packages/tailwindcss/src/compat/plugin-api.test.ts @@ -1592,11 +1592,7 @@ describe('addVariant', () => { .potato\\:flex:large-potato { display: flex; } - } - } - @media (width <= 400px) { - @supports (font: bold) { .potato\\:underline:large-potato { text-decoration-line: underline; } @@ -1840,19 +1836,7 @@ describe('matchVariant', () => { expect(optimizeCss(compiled).trim()).toMatchInlineSnapshot(` "@layer utilities { - .alphabet-d\\:underline[data-order="1"] { - text-decoration-line: underline; - } - - .alphabet-a\\:underline[data-order="2"] { - text-decoration-line: underline; - } - - .alphabet-c\\:underline[data-order="3"] { - text-decoration-line: underline; - } - - .alphabet-b\\:underline[data-order="4"] { + .alphabet-d\\:underline[data-order="1"], .alphabet-a\\:underline[data-order="2"], .alphabet-c\\:underline[data-order="3"], .alphabet-b\\:underline[data-order="4"] { text-decoration-line: underline; } }" @@ -2059,9 +2043,7 @@ describe('matchVariant', () => { order: 3; } } - } - @media (width >= 100px) { @media (width <= 300px) { .testmin-\\[100px\\]\\:testmax-\\[300px\\]\\:order-4 { order: 4; @@ -2116,11 +2098,7 @@ describe('matchVariant', () => { text-decoration-line: underline; } } - } - } - @media (width >= 100px) { - @media (width <= 200px) { .testmin-\\[100px\\]\\:testmax-\\[200px\\]\\:focus\\:underline:focus { text-decoration-line: underline; } @@ -2245,9 +2223,7 @@ describe('matchVariant', () => { text-decoration-line: underline; } } - } - @media (width <= 400px) { @media (width >= 200px) { .testmax-\\[400px\\]\\:testmin-\\[200px\\]\\:underline { text-decoration-line: underline; @@ -2261,9 +2237,7 @@ describe('matchVariant', () => { text-decoration-line: underline; } } - } - @media (width <= 300px) { @media (width >= 200px) { .testmax-\\[300px\\]\\:testmin-\\[200px\\]\\:underline { text-decoration-line: underline; @@ -2870,11 +2844,7 @@ describe('addUtilities()', () => { expect(optimizeCss(compiled.build(['form-input', 'lg:form-textarea'])).trim()) .toMatchInlineSnapshot(` - ".form-input { - background-color: red; - } - - .form-input::placeholder { + ".form-input, .form-input::placeholder { background-color: red; } @@ -3610,9 +3580,7 @@ describe('matchUtilities()', () => { --foo: 12px; display: flex; } - } - @media (width >= 1024px) { .lg\\:foo-bar { --foo: bar; display: flex; diff --git a/packages/tailwindcss/src/index.test.ts b/packages/tailwindcss/src/index.test.ts index 3a1b22b95623..c7dbe6373715 100644 --- a/packages/tailwindcss/src/index.test.ts +++ b/packages/tailwindcss/src/index.test.ts @@ -511,9 +511,7 @@ describe('variant stacking', () => { .before\\:hover\\:flex:before:hover { display: flex; } - } - @media (hover: hover) { .hover\\:before\\:flex:hover:before { content: var(--tw-content); display: flex; @@ -914,32 +912,14 @@ describe('sorting', () => { .peer-hover\\:flex:is(:where(.peer):hover ~ *) { display: flex; } - } - @media (hover: hover) { @media (hover: hover) { - .group-hover\\:peer-hover\\:flex:is(:where(.group):hover *):is(:where(.peer):hover ~ *) { + .group-hover\\:peer-hover\\:flex:is(:where(.group):hover *):is(:where(.peer):hover ~ *), .peer-hover\\:group-hover\\:flex:is(:where(.peer):hover ~ *):is(:where(.group):hover *) { display: flex; } } - } - @media (hover: hover) { - @media (hover: hover) { - .peer-hover\\:group-hover\\:flex:is(:where(.peer):hover ~ *):is(:where(.group):hover *) { - display: flex; - } - } - } - - @media (hover: hover) { - .group-focus\\:peer-hover\\:flex:is(:where(.group):focus *):is(:where(.peer):hover ~ *) { - display: flex; - } - } - - @media (hover: hover) { - .peer-hover\\:group-focus\\:flex:is(:where(.peer):hover ~ *):is(:where(.group):focus *) { + .group-focus\\:peer-hover\\:flex:is(:where(.group):focus *):is(:where(.peer):hover ~ *), .peer-hover\\:group-focus\\:flex:is(:where(.peer):hover ~ *):is(:where(.group):focus *) { display: flex; } } @@ -949,22 +929,12 @@ describe('sorting', () => { } @media (hover: hover) { - .group-hover\\:peer-focus\\:flex:is(:where(.group):hover *):is(:where(.peer):focus ~ *) { - display: flex; - } - } - - @media (hover: hover) { - .peer-focus\\:group-hover\\:flex:is(:where(.peer):focus ~ *):is(:where(.group):hover *) { + .group-hover\\:peer-focus\\:flex:is(:where(.group):hover *):is(:where(.peer):focus ~ *), .peer-focus\\:group-hover\\:flex:is(:where(.peer):focus ~ *):is(:where(.group):hover *) { display: flex; } } - .group-focus\\:peer-focus\\:flex:is(:where(.group):focus *):is(:where(.peer):focus ~ *) { - display: flex; - } - - .peer-focus\\:group-focus\\:flex:is(:where(.peer):focus ~ *):is(:where(.group):focus *) { + .group-focus\\:peer-focus\\:flex:is(:where(.group):focus *):is(:where(.peer):focus ~ *), .peer-focus\\:group-focus\\:flex:is(:where(.peer):focus ~ *):is(:where(.group):focus *) { display: flex; } @@ -2198,11 +2168,7 @@ describe('plugins', () => { expect(optimizeCss(compiled).trim()).toMatchInlineSnapshot(` "@layer utilities { - .rtl\\:flex:where(:dir(rtl), [dir="rtl"], [dir="rtl"] *) { - display: flex; - } - - .dark\\:flex:is([data-theme="dark"] *) { + .rtl\\:flex:where(:dir(rtl), [dir="rtl"], [dir="rtl"] *), .dark\\:flex:is([data-theme="dark"] *) { display: flex; } @@ -2386,11 +2352,7 @@ describe('@variant', () => { expect(optimizeCss(compiled).trim()).toMatchInlineSnapshot(` "@layer utilities { - .group-selected\\:underline:is(:where(.group)[data-selected] *) { - text-decoration-line: underline; - } - - .selected\\:underline[data-selected] { + .group-selected\\:underline:is(:where(.group)[data-selected] *), .selected\\:underline[data-selected] { text-decoration-line: underline; } }" @@ -2414,11 +2376,7 @@ describe('@variant', () => { expect(optimizeCss(compiled).trim()).toMatchInlineSnapshot(` "@layer utilities { - .group-hocus\\:underline:is(:is(:where(.group):hover, :where(.group):focus) *) { - text-decoration-line: underline; - } - - .hocus\\:underline:hover, .hocus\\:underline:focus { + .group-hocus\\:underline:is(:is(:where(.group):hover, :where(.group):focus) *), .hocus\\:underline:hover, .hocus\\:underline:focus { text-decoration-line: underline; } }" @@ -2445,11 +2403,7 @@ describe('@variant', () => { expect(optimizeCss(compiled).trim()).toMatchInlineSnapshot(` "@layer utilities { - .group-hocus\\:underline:is(:where(.group):hover *), .group-hocus\\:underline:is(:where(.group):focus *) { - text-decoration-line: underline; - } - - .hocus\\:underline:hover, .hocus\\:underline:focus { + .group-hocus\\:underline:is(:where(.group):hover *), .group-hocus\\:underline:is(:where(.group):focus *), .hocus\\:underline:hover, .hocus\\:underline:focus { text-decoration-line: underline; } }" @@ -2583,13 +2537,7 @@ describe('@variant', () => { expect(optimizeCss(compiled).trim()).toMatchInlineSnapshot(` "@layer utilities { @media (hover: hover) { - .group-hocus\\:underline:is(:where(.group):hover *) { - text-decoration-line: underline; - } - } - - @media (hover: hover) { - .hocus\\:underline:hover { + .group-hocus\\:underline:is(:where(.group):hover *), .hocus\\:underline:hover { text-decoration-line: underline; } } @@ -2745,11 +2693,7 @@ describe('@variant', () => { ), ).toMatchInlineSnapshot(` "@layer utilities { - .rtl\\:flex:where(:dir(rtl), [dir="rtl"], [dir="rtl"] *) { - display: flex; - } - - .dark\\:flex:is([data-theme="dark"] *) { + .rtl\\:flex:where(:dir(rtl), [dir="rtl"], [dir="rtl"] *), .dark\\:flex:is([data-theme="dark"] *) { display: flex; } diff --git a/packages/tailwindcss/src/test-utils/run.ts b/packages/tailwindcss/src/test-utils/run.ts index e8da80e3ade1..af6dc72e06eb 100644 --- a/packages/tailwindcss/src/test-utils/run.ts +++ b/packages/tailwindcss/src/test-utils/run.ts @@ -15,22 +15,28 @@ export function optimizeCss( input: string, { file = 'input.css', minify = false }: { file?: string; minify?: boolean } = {}, ) { - return transform({ - filename: file, - code: Buffer.from(input), - minify, - sourceMap: false, - drafts: { - customMedia: true, - }, - nonStandard: { - deepSelectorCombinator: true, - }, - include: Features.Nesting, - exclude: Features.LogicalProperties, - targets: { - safari: (16 << 16) | (4 << 8), - }, - errorRecovery: true, - }).code.toString() + function optimize(code: Buffer | Uint8Array) { + return transform({ + filename: file, + code, + minify, + sourceMap: false, + drafts: { + customMedia: true, + }, + nonStandard: { + deepSelectorCombinator: true, + }, + include: Features.Nesting, + exclude: Features.LogicalProperties, + targets: { + safari: (16 << 16) | (4 << 8), + }, + errorRecovery: true, + }).code + } + + // Running Lightning CSS twice to ensure that adjacent rules are merged after + // nesting is applied. This creates a more optimized output. + return optimize(optimize(Buffer.from(input))).toString() } diff --git a/packages/tailwindcss/src/utilities.test.ts b/packages/tailwindcss/src/utilities.test.ts index 6d94aa8348d2..429483aca354 100644 --- a/packages/tailwindcss/src/utilities.test.ts +++ b/packages/tailwindcss/src/utilities.test.ts @@ -6384,18 +6384,24 @@ test('color-scheme', async () => { ]), ).toMatchInlineSnapshot(` ".scheme-dark { + --lightningcss-light: ; + --lightningcss-dark: initial; --lightningcss-light: ; --lightningcss-dark: initial; color-scheme: dark; } .scheme-light { + --lightningcss-light: initial; + --lightningcss-dark: ; --lightningcss-light: initial; --lightningcss-dark: ; color-scheme: light; } .scheme-light-dark { + --lightningcss-light: initial; + --lightningcss-dark: ; --lightningcss-light: initial; --lightningcss-dark: ; color-scheme: light dark; @@ -6413,12 +6419,16 @@ test('color-scheme', async () => { } .scheme-only-dark { + --lightningcss-light: ; + --lightningcss-dark: initial; --lightningcss-light: ; --lightningcss-dark: initial; color-scheme: dark only; } .scheme-only-light { + --lightningcss-light: initial; + --lightningcss-dark: ; --lightningcss-light: initial; --lightningcss-dark: ; color-scheme: light only; @@ -8100,15 +8110,7 @@ test('divide-color', async () => { border-color: #08c; } - :where(.divide-\\[\\#0088cc\\]\\/50 > :not(:last-child)) { - border-color: oklch(59.9824% .14119 241.555 / .5); - } - - :where(.divide-\\[\\#0088cc\\]\\/\\[0\\.5\\] > :not(:last-child)) { - border-color: oklch(59.9824% .14119 241.555 / .5); - } - - :where(.divide-\\[\\#0088cc\\]\\/\\[50\\%\\] > :not(:last-child)) { + :where(.divide-\\[\\#0088cc\\]\\/50 > :not(:last-child)), :where(.divide-\\[\\#0088cc\\]\\/\\[0\\.5\\] > :not(:last-child)), :where(.divide-\\[\\#0088cc\\]\\/\\[50\\%\\] > :not(:last-child)) { border-color: oklch(59.9824% .14119 241.555 / .5); } @@ -8116,15 +8118,7 @@ test('divide-color', async () => { border-color: currentColor; } - :where(.divide-current\\/50 > :not(:last-child)) { - border-color: color-mix(in oklch, currentColor 50%, transparent); - } - - :where(.divide-current\\/\\[0\\.5\\] > :not(:last-child)) { - border-color: color-mix(in oklch, currentColor 50%, transparent); - } - - :where(.divide-current\\/\\[50\\%\\] > :not(:last-child)) { + :where(.divide-current\\/50 > :not(:last-child)), :where(.divide-current\\/\\[0\\.5\\] > :not(:last-child)), :where(.divide-current\\/\\[50\\%\\] > :not(:last-child)) { border-color: color-mix(in oklch, currentColor 50%, transparent); } @@ -8136,15 +8130,7 @@ test('divide-color', async () => { border-color: var(--color-red-500); } - :where(.divide-red-500\\/50 > :not(:last-child)) { - border-color: color-mix(in oklch, var(--color-red-500) 50%, transparent); - } - - :where(.divide-red-500\\/\\[0\\.5\\] > :not(:last-child)) { - border-color: color-mix(in oklch, var(--color-red-500) 50%, transparent); - } - - :where(.divide-red-500\\/\\[50\\%\\] > :not(:last-child)) { + :where(.divide-red-500\\/50 > :not(:last-child)), :where(.divide-red-500\\/\\[0\\.5\\] > :not(:last-child)), :where(.divide-red-500\\/\\[50\\%\\] > :not(:last-child)) { border-color: color-mix(in oklch, var(--color-red-500) 50%, transparent); } @@ -12553,15 +12539,7 @@ test('placeholder', async () => { color: #08c; } - .placeholder-\\[\\#0088cc\\]\\/50::placeholder { - color: oklch(59.9824% .14119 241.555 / .5); - } - - .placeholder-\\[\\#0088cc\\]\\/\\[0\\.5\\]::placeholder { - color: oklch(59.9824% .14119 241.555 / .5); - } - - .placeholder-\\[\\#0088cc\\]\\/\\[50\\%\\]::placeholder { + .placeholder-\\[\\#0088cc\\]\\/50::placeholder, .placeholder-\\[\\#0088cc\\]\\/\\[0\\.5\\]::placeholder, .placeholder-\\[\\#0088cc\\]\\/\\[50\\%\\]::placeholder { color: oklch(59.9824% .14119 241.555 / .5); } @@ -12569,15 +12547,7 @@ test('placeholder', async () => { color: currentColor; } - .placeholder-current\\/50::placeholder { - color: color-mix(in oklch, currentColor 50%, transparent); - } - - .placeholder-current\\/\\[0\\.5\\]::placeholder { - color: color-mix(in oklch, currentColor 50%, transparent); - } - - .placeholder-current\\/\\[50\\%\\]::placeholder { + .placeholder-current\\/50::placeholder, .placeholder-current\\/\\[0\\.5\\]::placeholder, .placeholder-current\\/\\[50\\%\\]::placeholder { color: color-mix(in oklch, currentColor 50%, transparent); } @@ -12589,15 +12559,7 @@ test('placeholder', async () => { color: var(--color-red-500); } - .placeholder-red-500\\/50::placeholder { - color: color-mix(in oklch, var(--color-red-500) 50%, transparent); - } - - .placeholder-red-500\\/\\[0\\.5\\]::placeholder { - color: color-mix(in oklch, var(--color-red-500) 50%, transparent); - } - - .placeholder-red-500\\/\\[50\\%\\]::placeholder { + .placeholder-red-500\\/50::placeholder, .placeholder-red-500\\/\\[0\\.5\\]::placeholder, .placeholder-red-500\\/\\[50\\%\\]::placeholder { color: color-mix(in oklch, var(--color-red-500) 50%, transparent); } @@ -12695,21 +12657,25 @@ test('decoration', async () => { } .decoration-\\[color\\:var\\(--my-color\\)\\] { + -webkit-text-decoration-color: var(--my-color); -webkit-text-decoration-color: var(--my-color); text-decoration-color: var(--my-color); } .decoration-\\[color\\:var\\(--my-color\\)\\]\\/50, .decoration-\\[color\\:var\\(--my-color\\)\\]\\/\\[0\\.5\\], .decoration-\\[color\\:var\\(--my-color\\)\\]\\/\\[50\\%\\] { + -webkit-text-decoration-color: color-mix(in oklch, var(--my-color) 50%, transparent); -webkit-text-decoration-color: color-mix(in oklch, var(--my-color) 50%, transparent); text-decoration-color: color-mix(in oklch, var(--my-color) 50%, transparent); } .decoration-\\[var\\(--my-color\\)\\] { + -webkit-text-decoration-color: var(--my-color); -webkit-text-decoration-color: var(--my-color); text-decoration-color: var(--my-color); } .decoration-\\[var\\(--my-color\\)\\]\\/50, .decoration-\\[var\\(--my-color\\)\\]\\/\\[0\\.5\\], .decoration-\\[var\\(--my-color\\)\\]\\/\\[50\\%\\] { + -webkit-text-decoration-color: color-mix(in oklch, var(--my-color) 50%, transparent); -webkit-text-decoration-color: color-mix(in oklch, var(--my-color) 50%, transparent); text-decoration-color: color-mix(in oklch, var(--my-color) 50%, transparent); } @@ -12719,21 +12685,25 @@ test('decoration', async () => { } .decoration-current\\/50, .decoration-current\\/\\[0\\.5\\], .decoration-current\\/\\[50\\%\\] { + -webkit-text-decoration-color: color-mix(in oklch, currentColor 50%, transparent); -webkit-text-decoration-color: color-mix(in oklch, currentColor 50%, transparent); text-decoration-color: color-mix(in oklch, currentColor 50%, transparent); } .decoration-inherit { + -webkit-text-decoration-color: inherit; -webkit-text-decoration-color: inherit; text-decoration-color: inherit; } .decoration-red-500 { + -webkit-text-decoration-color: var(--color-red-500); -webkit-text-decoration-color: var(--color-red-500); text-decoration-color: var(--color-red-500); } .decoration-red-500\\/50, .decoration-red-500\\/\\[0\\.5\\], .decoration-red-500\\/\\[50\\%\\] { + -webkit-text-decoration-color: color-mix(in oklch, var(--color-red-500) 50%, transparent); -webkit-text-decoration-color: color-mix(in oklch, var(--color-red-500) 50%, transparent); text-decoration-color: color-mix(in oklch, var(--color-red-500) 50%, transparent); } @@ -12787,7 +12757,7 @@ test('decoration', async () => { } .decoration-\\[50\\%\\] { - text-decoration-thickness: calc(1em / 2); + text-decoration-thickness: .5em; } .decoration-\\[length\\:var\\(--my-thickness\\)\\], .decoration-\\[percentage\\:var\\(--my-thickness\\)\\] { @@ -13616,7 +13586,7 @@ test('transition', async () => { } .transition { - transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to, opacity, box-shadow, transform, translate, scale, rotate, filter, -webkit-backdrop-filter, -webkit-backdrop-filter, backdrop-filter; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to, opacity, box-shadow, transform, translate, scale, rotate, filter, -webkit-backdrop-filter, -webkit-backdrop-filter, -webkit-backdrop-filter, backdrop-filter; transition-timing-function: var(--tw-ease, var(--default-transition-timing-function)); transition-duration: var(--tw-duration, var(--default-transition-duration)); } @@ -13683,7 +13653,7 @@ test('transition', async () => { } .transition { - transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to, opacity, box-shadow, transform, translate, scale, rotate, filter, -webkit-backdrop-filter, -webkit-backdrop-filter, backdrop-filter; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to, opacity, box-shadow, transform, translate, scale, rotate, filter, -webkit-backdrop-filter, -webkit-backdrop-filter, -webkit-backdrop-filter, backdrop-filter; transition-timing-function: var(--tw-ease, ease); transition-duration: var(--tw-duration, .1s); } diff --git a/packages/tailwindcss/src/variants.test.ts b/packages/tailwindcss/src/variants.test.ts index d34966506048..135e260aa1fa 100644 --- a/packages/tailwindcss/src/variants.test.ts +++ b/packages/tailwindcss/src/variants.test.ts @@ -137,15 +137,7 @@ test('after', async () => { test('first', async () => { expect(await run(['first:flex', 'group-first:flex', 'peer-first:flex'])).toMatchInlineSnapshot(` - ".group-first\\:flex:is(:where(.group):first-child *) { - display: flex; - } - - .peer-first\\:flex:is(:where(.peer):first-child ~ *) { - display: flex; - } - - .first\\:flex:first-child { + ".group-first\\:flex:is(:where(.group):first-child *), .peer-first\\:flex:is(:where(.peer):first-child ~ *), .first\\:flex:first-child { display: flex; }" `) @@ -154,15 +146,7 @@ test('first', async () => { test('last', async () => { expect(await run(['last:flex', 'group-last:flex', 'peer-last:flex'])).toMatchInlineSnapshot(` - ".group-last\\:flex:is(:where(.group):last-child *) { - display: flex; - } - - .peer-last\\:flex:is(:where(.peer):last-child ~ *) { - display: flex; - } - - .last\\:flex:last-child { + ".group-last\\:flex:is(:where(.group):last-child *), .peer-last\\:flex:is(:where(.peer):last-child ~ *), .last\\:flex:last-child { display: flex; }" `) @@ -171,15 +155,7 @@ test('last', async () => { test('only', async () => { expect(await run(['only:flex', 'group-only:flex', 'peer-only:flex'])).toMatchInlineSnapshot(` - ".group-only\\:flex:is(:where(.group):only-child *) { - display: flex; - } - - .peer-only\\:flex:is(:where(.peer):only-child ~ *) { - display: flex; - } - - .only\\:flex:only-child { + ".group-only\\:flex:is(:where(.group):only-child *), .peer-only\\:flex:is(:where(.peer):only-child ~ *), .only\\:flex:only-child { display: flex; }" `) @@ -188,15 +164,7 @@ test('only', async () => { test('odd', async () => { expect(await run(['odd:flex', 'group-odd:flex', 'peer-odd:flex'])).toMatchInlineSnapshot(` - ".group-odd\\:flex:is(:where(.group):nth-child(odd) *) { - display: flex; - } - - .peer-odd\\:flex:is(:where(.peer):nth-child(odd) ~ *) { - display: flex; - } - - .odd\\:flex:nth-child(odd) { + ".group-odd\\:flex:is(:where(.group):nth-child(odd) *), .peer-odd\\:flex:is(:where(.peer):nth-child(odd) ~ *), .odd\\:flex:nth-child(odd) { display: flex; }" `) @@ -205,15 +173,7 @@ test('odd', async () => { test('even', async () => { expect(await run(['even:flex', 'group-even:flex', 'peer-even:flex'])).toMatchInlineSnapshot(` - ".group-even\\:flex:is(:where(.group):nth-child(2n) *) { - display: flex; - } - - .peer-even\\:flex:is(:where(.peer):nth-child(2n) ~ *) { - display: flex; - } - - .even\\:flex:nth-child(2n) { + ".group-even\\:flex:is(:where(.group):nth-child(2n) *), .peer-even\\:flex:is(:where(.peer):nth-child(2n) ~ *), .even\\:flex:nth-child(2n) { display: flex; }" `) @@ -223,15 +183,7 @@ test('even', async () => { test('first-of-type', async () => { expect(await run(['first-of-type:flex', 'group-first-of-type:flex', 'peer-first-of-type:flex'])) .toMatchInlineSnapshot(` - ".group-first-of-type\\:flex:is(:where(.group):first-of-type *) { - display: flex; - } - - .peer-first-of-type\\:flex:is(:where(.peer):first-of-type ~ *) { - display: flex; - } - - .first-of-type\\:flex:first-of-type { + ".group-first-of-type\\:flex:is(:where(.group):first-of-type *), .peer-first-of-type\\:flex:is(:where(.peer):first-of-type ~ *), .first-of-type\\:flex:first-of-type { display: flex; }" `) @@ -241,15 +193,7 @@ test('first-of-type', async () => { test('last-of-type', async () => { expect(await run(['last-of-type:flex', 'group-last-of-type:flex', 'peer-last-of-type:flex'])) .toMatchInlineSnapshot(` - ".group-last-of-type\\:flex:is(:where(.group):last-of-type *) { - display: flex; - } - - .peer-last-of-type\\:flex:is(:where(.peer):last-of-type ~ *) { - display: flex; - } - - .last-of-type\\:flex:last-of-type { + ".group-last-of-type\\:flex:is(:where(.group):last-of-type *), .peer-last-of-type\\:flex:is(:where(.peer):last-of-type ~ *), .last-of-type\\:flex:last-of-type { display: flex; }" `) @@ -259,15 +203,7 @@ test('last-of-type', async () => { test('only-of-type', async () => { expect(await run(['only-of-type:flex', 'group-only-of-type:flex', 'peer-only-of-type:flex'])) .toMatchInlineSnapshot(` - ".group-only-of-type\\:flex:is(:where(.group):only-of-type *) { - display: flex; - } - - .peer-only-of-type\\:flex:is(:where(.peer):only-of-type ~ *) { - display: flex; - } - - .only-of-type\\:flex:only-of-type { + ".group-only-of-type\\:flex:is(:where(.group):only-of-type *), .peer-only-of-type\\:flex:is(:where(.peer):only-of-type ~ *), .only-of-type\\:flex:only-of-type { display: flex; }" `) @@ -277,50 +213,26 @@ test('only-of-type', async () => { test('visited', async () => { expect(await run(['visited:flex', 'group-visited:flex', 'peer-visited:flex'])) .toMatchInlineSnapshot(` - ".group-visited\\:flex:is(:where(.group):visited *) { - display: flex; - } - - .peer-visited\\:flex:is(:where(.peer):visited ~ *) { - display: flex; - } - - .visited\\:flex:visited { - display: flex; - }" - `) + ".group-visited\\:flex:is(:where(.group):visited *), .peer-visited\\:flex:is(:where(.peer):visited ~ *), .visited\\:flex:visited { + display: flex; + }" + `) expect(await run(['visited/foo:flex'])).toEqual('') }) test('target', async () => { expect(await run(['target:flex', 'group-target:flex', 'peer-target:flex'])) .toMatchInlineSnapshot(` - ".group-target\\:flex:is(:where(.group):target *) { - display: flex; - } - - .peer-target\\:flex:is(:where(.peer):target ~ *) { - display: flex; - } - - .target\\:flex:target { - display: flex; - }" - `) + ".group-target\\:flex:is(:where(.group):target *), .peer-target\\:flex:is(:where(.peer):target ~ *), .target\\:flex:target { + display: flex; + }" + `) expect(await run(['target/foo:flex'])).toEqual('') }) test('open', async () => { expect(await run(['open:flex', 'group-open:flex', 'peer-open:flex'])).toMatchInlineSnapshot(` - ".group-open\\:flex:is(:where(.group):is([open], :popover-open) *) { - display: flex; - } - - .peer-open\\:flex:is(:where(.peer):is([open], :popover-open) ~ *) { - display: flex; - } - - .open\\:flex:is([open], :popover-open) { + ".group-open\\:flex:is(:where(.group):is([open], :popover-open) *), .peer-open\\:flex:is(:where(.peer):is([open], :popover-open) ~ *), .open\\:flex:is([open], :popover-open) { display: flex; }" `) @@ -330,51 +242,27 @@ test('open', async () => { test('default', async () => { expect(await run(['default:flex', 'group-default:flex', 'peer-default:flex'])) .toMatchInlineSnapshot(` - ".group-default\\:flex:is(:where(.group):default *) { - display: flex; - } - - .peer-default\\:flex:is(:where(.peer):default ~ *) { - display: flex; - } - - .default\\:flex:default { - display: flex; - }" - `) + ".group-default\\:flex:is(:where(.group):default *), .peer-default\\:flex:is(:where(.peer):default ~ *), .default\\:flex:default { + display: flex; + }" + `) expect(await run(['default/foo:flex'])).toEqual('') }) test('checked', async () => { expect(await run(['checked:flex', 'group-checked:flex', 'peer-checked:flex'])) .toMatchInlineSnapshot(` - ".group-checked\\:flex:is(:where(.group):checked *) { - display: flex; - } - - .peer-checked\\:flex:is(:where(.peer):checked ~ *) { - display: flex; - } - - .checked\\:flex:checked { - display: flex; - }" - `) + ".group-checked\\:flex:is(:where(.group):checked *), .peer-checked\\:flex:is(:where(.peer):checked ~ *), .checked\\:flex:checked { + display: flex; + }" + `) expect(await run(['checked/foo:flex'])).toEqual('') }) test('indeterminate', async () => { expect(await run(['indeterminate:flex', 'group-indeterminate:flex', 'peer-indeterminate:flex'])) .toMatchInlineSnapshot(` - ".group-indeterminate\\:flex:is(:where(.group):indeterminate *) { - display: flex; - } - - .peer-indeterminate\\:flex:is(:where(.peer):indeterminate ~ *) { - display: flex; - } - - .indeterminate\\:flex:indeterminate { + ".group-indeterminate\\:flex:is(:where(.group):indeterminate *), .peer-indeterminate\\:flex:is(:where(.peer):indeterminate ~ *), .indeterminate\\:flex:indeterminate { display: flex; }" `) @@ -389,15 +277,7 @@ test('placeholder-shown', async () => { 'peer-placeholder-shown:flex', ]), ).toMatchInlineSnapshot(` - ".group-placeholder-shown\\:flex:is(:where(.group):placeholder-shown *) { - display: flex; - } - - .peer-placeholder-shown\\:flex:is(:where(.peer):placeholder-shown ~ *) { - display: flex; - } - - .placeholder-shown\\:flex:placeholder-shown { + ".group-placeholder-shown\\:flex:is(:where(.group):placeholder-shown *), .peer-placeholder-shown\\:flex:is(:where(.peer):placeholder-shown ~ *), .placeholder-shown\\:flex:placeholder-shown { display: flex; }" `) @@ -407,15 +287,7 @@ test('placeholder-shown', async () => { test('autofill', async () => { expect(await run(['autofill:flex', 'group-autofill:flex', 'peer-autofill:flex'])) .toMatchInlineSnapshot(` - ".group-autofill\\:flex:is(:where(.group):autofill *) { - display: flex; - } - - .peer-autofill\\:flex:is(:where(.peer):autofill ~ *) { - display: flex; - } - - .autofill\\:flex:autofill { + ".group-autofill\\:flex:is(:where(.group):autofill *), .peer-autofill\\:flex:is(:where(.peer):autofill ~ *), .autofill\\:flex:autofill { display: flex; }" `) @@ -425,15 +297,7 @@ test('autofill', async () => { test('optional', async () => { expect(await run(['optional:flex', 'group-optional:flex', 'peer-optional:flex'])) .toMatchInlineSnapshot(` - ".group-optional\\:flex:is(:where(.group):optional *) { - display: flex; - } - - .peer-optional\\:flex:is(:where(.peer):optional ~ *) { - display: flex; - } - - .optional\\:flex:optional { + ".group-optional\\:flex:is(:where(.group):optional *), .peer-optional\\:flex:is(:where(.peer):optional ~ *), .optional\\:flex:optional { display: flex; }" `) @@ -443,15 +307,7 @@ test('optional', async () => { test('required', async () => { expect(await run(['required:flex', 'group-required:flex', 'peer-required:flex'])) .toMatchInlineSnapshot(` - ".group-required\\:flex:is(:where(.group):required *) { - display: flex; - } - - .peer-required\\:flex:is(:where(.peer):required ~ *) { - display: flex; - } - - .required\\:flex:required { + ".group-required\\:flex:is(:where(.group):required *), .peer-required\\:flex:is(:where(.peer):required ~ *), .required\\:flex:required { display: flex; }" `) @@ -460,15 +316,7 @@ test('required', async () => { test('valid', async () => { expect(await run(['valid:flex', 'group-valid:flex', 'peer-valid:flex'])).toMatchInlineSnapshot(` - ".group-valid\\:flex:is(:where(.group):valid *) { - display: flex; - } - - .peer-valid\\:flex:is(:where(.peer):valid ~ *) { - display: flex; - } - - .valid\\:flex:valid { + ".group-valid\\:flex:is(:where(.group):valid *), .peer-valid\\:flex:is(:where(.peer):valid ~ *), .valid\\:flex:valid { display: flex; }" `) @@ -478,33 +326,17 @@ test('valid', async () => { test('invalid', async () => { expect(await run(['invalid:flex', 'group-invalid:flex', 'peer-invalid:flex'])) .toMatchInlineSnapshot(` - ".group-invalid\\:flex:is(:where(.group):invalid *) { - display: flex; - } - - .peer-invalid\\:flex:is(:where(.peer):invalid ~ *) { - display: flex; - } - - .invalid\\:flex:invalid { - display: flex; - }" - `) + ".group-invalid\\:flex:is(:where(.group):invalid *), .peer-invalid\\:flex:is(:where(.peer):invalid ~ *), .invalid\\:flex:invalid { + display: flex; + }" + `) expect(await run(['invalid/foo:flex'])).toEqual('') }) test('in-range', async () => { expect(await run(['in-range:flex', 'group-in-range:flex', 'peer-in-range:flex'])) .toMatchInlineSnapshot(` - ".group-in-range\\:flex:is(:where(.group):in-range *) { - display: flex; - } - - .peer-in-range\\:flex:is(:where(.peer):in-range ~ *) { - display: flex; - } - - .in-range\\:flex:in-range { + ".group-in-range\\:flex:is(:where(.group):in-range *), .peer-in-range\\:flex:is(:where(.peer):in-range ~ *), .in-range\\:flex:in-range { display: flex; }" `) @@ -514,15 +346,7 @@ test('in-range', async () => { test('out-of-range', async () => { expect(await run(['out-of-range:flex', 'group-out-of-range:flex', 'peer-out-of-range:flex'])) .toMatchInlineSnapshot(` - ".group-out-of-range\\:flex:is(:where(.group):out-of-range *) { - display: flex; - } - - .peer-out-of-range\\:flex:is(:where(.peer):out-of-range ~ *) { - display: flex; - } - - .out-of-range\\:flex:out-of-range { + ".group-out-of-range\\:flex:is(:where(.group):out-of-range *), .peer-out-of-range\\:flex:is(:where(.peer):out-of-range ~ *), .out-of-range\\:flex:out-of-range { display: flex; }" `) @@ -532,15 +356,7 @@ test('out-of-range', async () => { test('read-only', async () => { expect(await run(['read-only:flex', 'group-read-only:flex', 'peer-read-only:flex'])) .toMatchInlineSnapshot(` - ".group-read-only\\:flex:is(:where(.group):read-only *) { - display: flex; - } - - .peer-read-only\\:flex:is(:where(.peer):read-only ~ *) { - display: flex; - } - - .read-only\\:flex:read-only { + ".group-read-only\\:flex:is(:where(.group):read-only *), .peer-read-only\\:flex:is(:where(.peer):read-only ~ *), .read-only\\:flex:read-only { display: flex; }" `) @@ -549,15 +365,7 @@ test('read-only', async () => { test('empty', async () => { expect(await run(['empty:flex', 'group-empty:flex', 'peer-empty:flex'])).toMatchInlineSnapshot(` - ".group-empty\\:flex:is(:where(.group):empty *) { - display: flex; - } - - .peer-empty\\:flex:is(:where(.peer):empty ~ *) { - display: flex; - } - - .empty\\:flex:empty { + ".group-empty\\:flex:is(:where(.group):empty *), .peer-empty\\:flex:is(:where(.peer):empty ~ *), .empty\\:flex:empty { display: flex; }" `) @@ -567,15 +375,7 @@ test('empty', async () => { test('focus-within', async () => { expect(await run(['focus-within:flex', 'group-focus-within:flex', 'peer-focus-within:flex'])) .toMatchInlineSnapshot(` - ".group-focus-within\\:flex:is(:where(.group):focus-within *) { - display: flex; - } - - .peer-focus-within\\:flex:is(:where(.peer):focus-within ~ *) { - display: flex; - } - - .focus-within\\:flex:focus-within { + ".group-focus-within\\:flex:is(:where(.group):focus-within *), .peer-focus-within\\:flex:is(:where(.peer):focus-within ~ *), .focus-within\\:flex:focus-within { display: flex; }" `) @@ -585,19 +385,7 @@ test('focus-within', async () => { test('hover', async () => { expect(await run(['hover:flex', 'group-hover:flex', 'peer-hover:flex'])).toMatchInlineSnapshot(` "@media (hover: hover) { - .group-hover\\:flex:is(:where(.group):hover *) { - display: flex; - } - } - - @media (hover: hover) { - .peer-hover\\:flex:is(:where(.peer):hover ~ *) { - display: flex; - } - } - - @media (hover: hover) { - .hover\\:flex:hover { + .group-hover\\:flex:is(:where(.group):hover *), .peer-hover\\:flex:is(:where(.peer):hover ~ *), .hover\\:flex:hover { display: flex; } }" @@ -607,15 +395,7 @@ test('hover', async () => { test('focus', async () => { expect(await run(['focus:flex', 'group-focus:flex', 'peer-focus:flex'])).toMatchInlineSnapshot(` - ".group-focus\\:flex:is(:where(.group):focus *) { - display: flex; - } - - .peer-focus\\:flex:is(:where(.peer):focus ~ *) { - display: flex; - } - - .focus\\:flex:focus { + ".group-focus\\:flex:is(:where(.group):focus *), .peer-focus\\:flex:is(:where(.peer):focus ~ *), .focus\\:flex:focus { display: flex; }" `) @@ -650,15 +430,7 @@ test('group-hover group-focus sorting', async () => { test('focus-visible', async () => { expect(await run(['focus-visible:flex', 'group-focus-visible:flex', 'peer-focus-visible:flex'])) .toMatchInlineSnapshot(` - ".group-focus-visible\\:flex:is(:where(.group):focus-visible *) { - display: flex; - } - - .peer-focus-visible\\:flex:is(:where(.peer):focus-visible ~ *) { - display: flex; - } - - .focus-visible\\:flex:focus-visible { + ".group-focus-visible\\:flex:is(:where(.group):focus-visible *), .peer-focus-visible\\:flex:is(:where(.peer):focus-visible ~ *), .focus-visible\\:flex:focus-visible { display: flex; }" `) @@ -668,51 +440,27 @@ test('focus-visible', async () => { test('active', async () => { expect(await run(['active:flex', 'group-active:flex', 'peer-active:flex'])) .toMatchInlineSnapshot(` - ".group-active\\:flex:is(:where(.group):active *) { - display: flex; - } - - .peer-active\\:flex:is(:where(.peer):active ~ *) { - display: flex; - } - - .active\\:flex:active { - display: flex; - }" - `) + ".group-active\\:flex:is(:where(.group):active *), .peer-active\\:flex:is(:where(.peer):active ~ *), .active\\:flex:active { + display: flex; + }" + `) expect(await run(['active/foo:flex'])).toEqual('') }) test('enabled', async () => { expect(await run(['enabled:flex', 'group-enabled:flex', 'peer-enabled:flex'])) .toMatchInlineSnapshot(` - ".group-enabled\\:flex:is(:where(.group):enabled *) { - display: flex; - } - - .peer-enabled\\:flex:is(:where(.peer):enabled ~ *) { - display: flex; - } - - .enabled\\:flex:enabled { - display: flex; - }" - `) + ".group-enabled\\:flex:is(:where(.group):enabled *), .peer-enabled\\:flex:is(:where(.peer):enabled ~ *), .enabled\\:flex:enabled { + display: flex; + }" + `) expect(await run(['enabled/foo:flex'])).toEqual('') }) test('disabled', async () => { expect(await run(['disabled:flex', 'group-disabled:flex', 'peer-disabled:flex'])) .toMatchInlineSnapshot(` - ".group-disabled\\:flex:is(:where(.group):disabled *) { - display: flex; - } - - .peer-disabled\\:flex:is(:where(.peer):disabled ~ *) { - display: flex; - } - - .disabled\\:flex:disabled { + ".group-disabled\\:flex:is(:where(.group):disabled *), .peer-disabled\\:flex:is(:where(.peer):disabled ~ *), .disabled\\:flex:disabled { display: flex; }" `) @@ -721,15 +469,7 @@ test('disabled', async () => { test('inert', async () => { expect(await run(['inert:flex', 'group-inert:flex', 'peer-inert:flex'])).toMatchInlineSnapshot(` - ".group-inert\\:flex:is(:where(.group):is([inert], [inert] *) *) { - display: flex; - } - - .peer-inert\\:flex:is(:where(.peer):is([inert], [inert] *) ~ *) { - display: flex; - } - - .inert\\:flex:is([inert], [inert] *) { + ".group-inert\\:flex:is(:where(.group):is([inert], [inert] *) *), .peer-inert\\:flex:is(:where(.peer):is([inert], [inert] *) ~ *), .inert\\:flex:is([inert], [inert] *) { display: flex; }" `) @@ -746,27 +486,15 @@ test('group-[...]', async () => { 'group-[&:hover]:group-[&_p]:flex', ]), ).toMatchInlineSnapshot(` - ".group-\\[\\&_p\\]\\:flex:is(:where(.group) p *) { - display: flex; - } - - .group-\\[\\&\\:hover\\]\\:group-\\[\\&_p\\]\\:flex:is(:where(.group):hover *):is(:where(.group) p *) { + ".group-\\[\\&_p\\]\\:flex:is(:where(.group) p *), .group-\\[\\&\\:hover\\]\\:group-\\[\\&_p\\]\\:flex:is(:where(.group):hover *):is(:where(.group) p *) { display: flex; } @media (hover: hover) { - .group-\\[\\&_p\\]\\:hover\\:flex:is(:where(.group) p *):hover { - display: flex; - } - } - - @media (hover: hover) { - .hover\\:group-\\[\\&_p\\]\\:flex:hover:is(:where(.group) p *) { + .group-\\[\\&_p\\]\\:hover\\:flex:is(:where(.group) p *):hover, .hover\\:group-\\[\\&_p\\]\\:flex:hover:is(:where(.group) p *) { display: flex; } - } - @media (hover: hover) { @media (hover: hover) { .hover\\:group-\\[\\&_p\\]\\:hover\\:flex:hover:is(:where(.group) p *):hover { display: flex; @@ -818,13 +546,7 @@ test('group-*', async () => { } @media (hover: hover) { - .group-focus\\:group-hover\\:flex:is(:where(.group):focus *):is(:where(.group):hover *) { - display: flex; - } - } - - @media (hover: hover) { - .group-hover\\:group-focus\\:flex:is(:where(.group):hover *):is(:where(.group):focus *) { + .group-focus\\:group-hover\\:flex:is(:where(.group):focus *):is(:where(.group):hover *), .group-hover\\:group-focus\\:flex:is(:where(.group):hover *):is(:where(.group):focus *) { display: flex; } } @@ -862,28 +584,12 @@ test('peer-[...]', async () => { 'peer-[&:hover]:peer-[&_p]:flex', ]), ).toMatchInlineSnapshot(` - ".peer-\\[\\&_p\\]\\:flex:is(:where(.peer) p ~ *) { - display: flex; - } - - .peer-\\[\\&\\:hover\\]\\:peer-\\[\\&_p\\]\\:flex:is(:where(.peer):hover ~ *):is(:where(.peer) p ~ *) { + ".peer-\\[\\&_p\\]\\:flex:is(:where(.peer) p ~ *), .peer-\\[\\&\\:hover\\]\\:peer-\\[\\&_p\\]\\:flex:is(:where(.peer):hover ~ *):is(:where(.peer) p ~ *) { display: flex; } @media (hover: hover) { - .hover\\:peer-\\[\\&_p\\]\\:flex:hover:is(:where(.peer) p ~ *) { - display: flex; - } - } - - @media (hover: hover) { - .peer-\\[\\&_p\\]\\:hover\\:flex:is(:where(.peer) p ~ *):hover { - display: flex; - } - } - - @media (hover: hover) { - .hover\\:peer-\\[\\&_p\\]\\:focus\\:flex:hover:is(:where(.peer) p ~ *):focus { + .hover\\:peer-\\[\\&_p\\]\\:flex:hover:is(:where(.peer) p ~ *), .peer-\\[\\&_p\\]\\:hover\\:flex:is(:where(.peer) p ~ *):hover, .hover\\:peer-\\[\\&_p\\]\\:focus\\:flex:hover:is(:where(.peer) p ~ *):focus { display: flex; } }" @@ -931,13 +637,7 @@ test('peer-*', async () => { } @media (hover: hover) { - .peer-focus\\:peer-hover\\:flex:is(:where(.peer):focus ~ *):is(:where(.peer):hover ~ *) { - display: flex; - } - } - - @media (hover: hover) { - .peer-hover\\:peer-focus\\:flex:is(:where(.peer):hover ~ *):is(:where(.peer):focus ~ *) { + .peer-focus\\:peer-hover\\:flex:is(:where(.peer):focus ~ *):is(:where(.peer):hover ~ *), .peer-hover\\:peer-focus\\:flex:is(:where(.peer):hover ~ *):is(:where(.peer):focus ~ *) { display: flex; } } @@ -1284,9 +984,7 @@ test('sorting stacked min-* and max-* variants', async () => { display: flex; } } - } - @media (width >= 640px) { @media (width < 1024px) { .min-sm\\:max-lg\\:flex { display: flex; @@ -1329,9 +1027,7 @@ test('stacked min-* and max-* variants should come after unprefixed variants', a .sm\\:flex { display: flex; } - } - @media (width >= 640px) { @media (width < 1024px) { .min-sm\\:max-lg\\:flex { display: flex; @@ -1343,9 +1039,7 @@ test('stacked min-* and max-* variants should come after unprefixed variants', a .md\\:flex { display: flex; } - } - @media (width >= 768px) { @media (width < 1024px) { .min-md\\:max-lg\\:flex { display: flex; @@ -1416,13 +1110,7 @@ test('min, max and unprefixed breakpoints', async () => { } @media (width >= 640px) { - .min-sm\\:flex { - display: flex; - } - } - - @media (width >= 640px) { - .sm\\:flex { + .min-sm\\:flex, .sm\\:flex { display: flex; } } @@ -1434,25 +1122,13 @@ test('min, max and unprefixed breakpoints', async () => { } @media (width >= 768px) { - .md\\:flex { - display: flex; - } - } - - @media (width >= 768px) { - .min-md\\:flex { + .md\\:flex, .min-md\\:flex { display: flex; } } @media (width >= 1024px) { - .lg\\:flex { - display: flex; - } - } - - @media (width >= 1024px) { - .min-lg\\:flex { + .lg\\:flex, .min-lg\\:flex { display: flex; } }" @@ -1792,43 +1468,7 @@ test('not', async () => { --breakpoint-sm: 640px; } - .not-first\\:flex:not(:first-child) { - display: flex; - } - - .not-last\\:flex:not(:last-child) { - display: flex; - } - - .not-only\\:flex:not(:only-child) { - display: flex; - } - - .not-odd\\:flex:not(:nth-child(odd)) { - display: flex; - } - - .not-even\\:flex:not(:nth-child(2n)) { - display: flex; - } - - .not-first-of-type\\:flex:not(:first-of-type) { - display: flex; - } - - .not-last-of-type\\:flex:not(:last-of-type) { - display: flex; - } - - .not-only-of-type\\:flex:not(:only-of-type) { - display: flex; - } - - .not-visited\\:flex:not(:visited) { - display: flex; - } - - .not-target\\:flex:not(:target) { + .not-first\\:flex:not(:first-child), .not-last\\:flex:not(:last-child), .not-only\\:flex:not(:only-child), .not-odd\\:flex:not(:nth-child(odd)), .not-even\\:flex:not(:nth-child(2n)), .not-first-of-type\\:flex:not(:first-of-type), .not-last-of-type\\:flex:not(:last-of-type), .not-only-of-type\\:flex:not(:only-of-type), .not-visited\\:flex:not(:visited), .not-target\\:flex:not(:target) { display: flex; } @@ -1836,63 +1476,7 @@ test('not', async () => { display: flex; } - .not-default\\:flex:not(:default) { - display: flex; - } - - .not-checked\\:flex:not(:checked) { - display: flex; - } - - .not-indeterminate\\:flex:not(:indeterminate) { - display: flex; - } - - .not-placeholder-shown\\:flex:not(:placeholder-shown) { - display: flex; - } - - .not-autofill\\:flex:not(:autofill) { - display: flex; - } - - .not-optional\\:flex:not(:optional) { - display: flex; - } - - .not-required\\:flex:not(:required) { - display: flex; - } - - .not-valid\\:flex:not(:valid) { - display: flex; - } - - .not-invalid\\:flex:not(:invalid) { - display: flex; - } - - .not-in-range\\:flex:not(:in-range) { - display: flex; - } - - .not-out-of-range\\:flex:not(:out-of-range) { - display: flex; - } - - .not-read-only\\:flex:not(:read-only) { - display: flex; - } - - .not-empty\\:flex:not(:empty) { - display: flex; - } - - .not-focus-within\\:flex:not(:focus-within) { - display: flex; - } - - .not-hover\\:flex:not(:hover) { + .not-default\\:flex:not(:default), .not-checked\\:flex:not(:checked), .not-indeterminate\\:flex:not(:indeterminate), .not-placeholder-shown\\:flex:not(:placeholder-shown), .not-autofill\\:flex:not(:autofill), .not-optional\\:flex:not(:optional), .not-required\\:flex:not(:required), .not-valid\\:flex:not(:valid), .not-invalid\\:flex:not(:invalid), .not-in-range\\:flex:not(:in-range), .not-out-of-range\\:flex:not(:out-of-range), .not-read-only\\:flex:not(:read-only), .not-empty\\:flex:not(:empty), .not-focus-within\\:flex:not(:focus-within), .not-hover\\:flex:not(:hover) { display: flex; } @@ -1902,43 +1486,7 @@ test('not', async () => { } } - .not-focus\\:flex:not(:focus) { - display: flex; - } - - .not-focus-visible\\:flex:not(:focus-visible) { - display: flex; - } - - .not-active\\:flex:not(:active) { - display: flex; - } - - .not-enabled\\:flex:not(:enabled) { - display: flex; - } - - .not-disabled\\:flex:not(:disabled) { - display: flex; - } - - .not-inert\\:flex:not([inert], [inert] *) { - display: flex; - } - - .not-has-checked\\:flex:not(:has(:checked)) { - display: flex; - } - - .not-aria-selected\\:flex:not([aria-selected="true"]) { - display: flex; - } - - .not-data-foo\\:flex:not([data-foo]) { - display: flex; - } - - .not-nth-2\\:flex:not(:nth-child(2)) { + .not-focus\\:flex:not(:focus), .not-focus-visible\\:flex:not(:focus-visible), .not-active\\:flex:not(:active), .not-enabled\\:flex:not(:enabled), .not-disabled\\:flex:not(:disabled), .not-inert\\:flex:not([inert], [inert] *), .not-has-checked\\:flex:not(:has(:checked)), .not-aria-selected\\:flex:not([aria-selected="true"]), .not-data-foo\\:flex:not([data-foo]), .not-nth-2\\:flex:not(:nth-child(2)) { display: flex; } @@ -1991,13 +1539,7 @@ test('not', async () => { } @media not (width >= 640px) { - .not-min-sm\\:flex { - display: flex; - } - } - - @media not (width >= 640px) { - .not-sm\\:flex { + .not-min-sm\\:flex, .not-sm\\:flex { display: flex; } } @@ -2014,11 +1556,7 @@ test('not', async () => { } } - .not-ltr\\:flex:not(:where(:dir(ltr), [dir="ltr"], [dir="ltr"] *)) { - display: flex; - } - - .not-rtl\\:flex:not(:where(:dir(rtl), [dir="rtl"], [dir="rtl"] *)) { + .not-ltr\\:flex:not(:where(:dir(ltr), [dir="ltr"], [dir="ltr"] *)), .not-rtl\\:flex:not(:where(:dir(rtl), [dir="rtl"], [dir="rtl"] *)) { display: flex; } @@ -2040,11 +1578,7 @@ test('not', async () => { } } - .not-hocus\\:flex:not(:hover, :focus) { - display: flex; - } - - .not-device-hocus\\:flex:not(:hover, :focus) { + .not-hocus\\:flex:not(:hover, :focus), .not-device-hocus\\:flex:not(:hover, :focus) { display: flex; } @@ -2082,43 +1616,7 @@ test('not', async () => { } } - .group-not-checked\\:flex:is(:where(.group):not(:checked) *) { - display: flex; - } - - .group-not-hocus\\:flex:is(:where(.group):not(:hover, :focus) *) { - display: flex; - } - - .group-not-hocus\\/parent-name\\:flex:is(:where(.group\\/parent-name):not(:hover, :focus) *) { - display: flex; - } - - .group-not-\\[\\:checked\\]\\:flex:is(:where(.group):not(:checked) *) { - display: flex; - } - - .group-not-\\[\\:checked\\]\\/parent-name\\:flex:is(:where(.group\\/parent-name):not(:checked) *) { - display: flex; - } - - .peer-not-checked\\:flex:is(:where(.peer):not(:checked) ~ *) { - display: flex; - } - - .peer-not-hocus\\:flex:is(:where(.peer):not(:hover, :focus) ~ *) { - display: flex; - } - - .peer-not-hocus\\/sibling-name\\:flex:is(:where(.peer\\/sibling-name):not(:hover, :focus) ~ *) { - display: flex; - } - - .peer-not-\\[\\:checked\\]\\:flex:is(:where(.peer):not(:checked) ~ *) { - display: flex; - } - - .peer-not-\\[\\:checked\\]\\/sibling-name\\:flex:is(:where(.peer\\/sibling-name):not(:checked) ~ *) { + .group-not-checked\\:flex:is(:where(.group):not(:checked) *), .group-not-hocus\\:flex:is(:where(.group):not(:hover, :focus) *), .group-not-hocus\\/parent-name\\:flex:is(:where(.group\\/parent-name):not(:hover, :focus) *), .group-not-\\[\\:checked\\]\\:flex:is(:where(.group):not(:checked) *), .group-not-\\[\\:checked\\]\\/parent-name\\:flex:is(:where(.group\\/parent-name):not(:checked) *), .peer-not-checked\\:flex:is(:where(.peer):not(:checked) ~ *), .peer-not-hocus\\:flex:is(:where(.peer):not(:hover, :focus) ~ *), .peer-not-hocus\\/sibling-name\\:flex:is(:where(.peer\\/sibling-name):not(:hover, :focus) ~ *), .peer-not-\\[\\:checked\\]\\:flex:is(:where(.peer):not(:checked) ~ *), .peer-not-\\[\\:checked\\]\\/sibling-name\\:flex:is(:where(.peer\\/sibling-name):not(:checked) ~ *) { display: flex; }" `) @@ -2235,127 +1733,7 @@ test('has', async () => { ], ), ).toMatchInlineSnapshot(` - ".group-has-checked\\:flex:is(:where(.group):has(:checked) *) { - display: flex; - } - - .group-has-checked\\/parent-name\\:flex:is(:where(.group\\/parent-name):has(:checked) *) { - display: flex; - } - - .group-has-hocus\\:flex:is(:where(.group):has(:hover, :focus) *) { - display: flex; - } - - .group-has-hocus\\/parent-name\\:flex:is(:where(.group\\/parent-name):has(:hover, :focus) *) { - display: flex; - } - - .group-has-\\[\\:checked\\]\\:flex:is(:where(.group):has(:checked) *) { - display: flex; - } - - .group-has-\\[\\:checked\\]\\/parent-name\\:flex:is(:where(.group\\/parent-name):has(:checked) *) { - display: flex; - } - - .group-has-\\[\\&\\>img\\]\\:flex:is(:where(.group):has(* > img) *) { - display: flex; - } - - .group-has-\\[\\&\\>img\\]\\/parent-name\\:flex:is(:where(.group\\/parent-name):has(* > img) *) { - display: flex; - } - - .group-has-\\[\\+img\\]\\:flex:is(:where(.group):has( + img) *) { - display: flex; - } - - .group-has-\\[\\>img\\]\\:flex:is(:where(.group):has( > img) *) { - display: flex; - } - - .group-has-\\[\\>img\\]\\/parent-name\\:flex:is(:where(.group\\/parent-name):has( > img) *) { - display: flex; - } - - .group-has-\\[\\~img\\]\\:flex:is(:where(.group):has( ~ img) *) { - display: flex; - } - - .peer-has-checked\\:flex:is(:where(.peer):has(:checked) ~ *) { - display: flex; - } - - .peer-has-checked\\/sibling-name\\:flex:is(:where(.peer\\/sibling-name):has(:checked) ~ *) { - display: flex; - } - - .peer-has-hocus\\:flex:is(:where(.peer):has(:hover, :focus) ~ *) { - display: flex; - } - - .peer-has-hocus\\/sibling-name\\:flex:is(:where(.peer\\/sibling-name):has(:hover, :focus) ~ *) { - display: flex; - } - - .peer-has-\\[\\:checked\\]\\:flex:is(:where(.peer):has(:checked) ~ *) { - display: flex; - } - - .peer-has-\\[\\:checked\\]\\/sibling-name\\:flex:is(:where(.peer\\/sibling-name):has(:checked) ~ *) { - display: flex; - } - - .peer-has-\\[\\&\\>img\\]\\:flex:is(:where(.peer):has(* > img) ~ *) { - display: flex; - } - - .peer-has-\\[\\&\\>img\\]\\/sibling-name\\:flex:is(:where(.peer\\/sibling-name):has(* > img) ~ *) { - display: flex; - } - - .peer-has-\\[\\+img\\]\\:flex:is(:where(.peer):has( + img) ~ *) { - display: flex; - } - - .peer-has-\\[\\>img\\]\\:flex:is(:where(.peer):has( > img) ~ *) { - display: flex; - } - - .peer-has-\\[\\>img\\]\\/sibling-name\\:flex:is(:where(.peer\\/sibling-name):has( > img) ~ *) { - display: flex; - } - - .peer-has-\\[\\~img\\]\\:flex:is(:where(.peer):has( ~ img) ~ *) { - display: flex; - } - - .has-checked\\:flex:has(:checked) { - display: flex; - } - - .has-hocus\\:flex:has(:hover, :focus) { - display: flex; - } - - .has-\\[\\:checked\\]\\:flex:has(:checked) { - display: flex; - } - - .has-\\[\\&\\>img\\]\\:flex:has(* > img) { - display: flex; - } - - .has-\\[\\+img\\]\\:flex:has( + img) { - display: flex; - } - - .has-\\[\\>img\\]\\:flex:has( > img) { - display: flex; - } - - .has-\\[\\~img\\]\\:flex:has( ~ img) { + ".group-has-checked\\:flex:is(:where(.group):has(:checked) *), .group-has-checked\\/parent-name\\:flex:is(:where(.group\\/parent-name):has(:checked) *), .group-has-hocus\\:flex:is(:where(.group):has(:hover, :focus) *), .group-has-hocus\\/parent-name\\:flex:is(:where(.group\\/parent-name):has(:hover, :focus) *), .group-has-\\[\\:checked\\]\\:flex:is(:where(.group):has(:checked) *), .group-has-\\[\\:checked\\]\\/parent-name\\:flex:is(:where(.group\\/parent-name):has(:checked) *), .group-has-\\[\\&\\>img\\]\\:flex:is(:where(.group):has(* > img) *), .group-has-\\[\\&\\>img\\]\\/parent-name\\:flex:is(:where(.group\\/parent-name):has(* > img) *), .group-has-\\[\\+img\\]\\:flex:is(:where(.group):has( + img) *), .group-has-\\[\\>img\\]\\:flex:is(:where(.group):has( > img) *), .group-has-\\[\\>img\\]\\/parent-name\\:flex:is(:where(.group\\/parent-name):has( > img) *), .group-has-\\[\\~img\\]\\:flex:is(:where(.group):has( ~ img) *), .peer-has-checked\\:flex:is(:where(.peer):has(:checked) ~ *), .peer-has-checked\\/sibling-name\\:flex:is(:where(.peer\\/sibling-name):has(:checked) ~ *), .peer-has-hocus\\:flex:is(:where(.peer):has(:hover, :focus) ~ *), .peer-has-hocus\\/sibling-name\\:flex:is(:where(.peer\\/sibling-name):has(:hover, :focus) ~ *), .peer-has-\\[\\:checked\\]\\:flex:is(:where(.peer):has(:checked) ~ *), .peer-has-\\[\\:checked\\]\\/sibling-name\\:flex:is(:where(.peer\\/sibling-name):has(:checked) ~ *), .peer-has-\\[\\&\\>img\\]\\:flex:is(:where(.peer):has(* > img) ~ *), .peer-has-\\[\\&\\>img\\]\\/sibling-name\\:flex:is(:where(.peer\\/sibling-name):has(* > img) ~ *), .peer-has-\\[\\+img\\]\\:flex:is(:where(.peer):has( + img) ~ *), .peer-has-\\[\\>img\\]\\:flex:is(:where(.peer):has( > img) ~ *), .peer-has-\\[\\>img\\]\\/sibling-name\\:flex:is(:where(.peer\\/sibling-name):has( > img) ~ *), .peer-has-\\[\\~img\\]\\:flex:is(:where(.peer):has( ~ img) ~ *), .has-checked\\:flex:has(:checked), .has-hocus\\:flex:has(:hover, :focus), .has-\\[\\:checked\\]\\:flex:has(:checked), .has-\\[\\&\\>img\\]\\:flex:has(* > img), .has-\\[\\+img\\]\\:flex:has( + img), .has-\\[\\>img\\]\\:flex:has( > img), .has-\\[\\~img\\]\\:flex:has( ~ img) { display: flex; }" `) @@ -2400,198 +1778,50 @@ test('aria', async () => { 'peer-aria-[modal]:flex', 'peer-aria-checked:flex', - 'peer-aria-[valuenow=1]:flex', - 'peer-aria-[modal]/sibling-name:flex', - 'peer-aria-checked/sibling-name:flex', - 'peer-aria-[valuenow=1]/sibling-name:flex', - ]), - ).toMatchInlineSnapshot(` - ".group-aria-checked\\:flex:is(:where(.group)[aria-checked="true"] *) { - display: flex; - } - - .group-aria-checked\\/parent-name\\:flex:is(:where(.group\\/parent-name)[aria-checked="true"] *) { - display: flex; - } - - .group-aria-\\[modal\\]\\:flex:is(:where(.group)[aria-modal] *) { - display: flex; - } - - .group-aria-\\[modal\\]\\/parent-name\\:flex:is(:where(.group\\/parent-name)[aria-modal] *) { - display: flex; - } - - .group-aria-\\[valuenow\\=1\\]\\:flex:is(:where(.group)[aria-valuenow="1"] *) { - display: flex; - } - - .group-aria-\\[valuenow\\=1\\]\\/parent-name\\:flex:is(:where(.group\\/parent-name)[aria-valuenow="1"] *) { - display: flex; - } - - .peer-aria-checked\\:flex:is(:where(.peer)[aria-checked="true"] ~ *) { - display: flex; - } - - .peer-aria-checked\\/sibling-name\\:flex:is(:where(.peer\\/sibling-name)[aria-checked="true"] ~ *) { - display: flex; - } - - .peer-aria-\\[modal\\]\\:flex:is(:where(.peer)[aria-modal] ~ *) { - display: flex; - } - - .peer-aria-\\[modal\\]\\/sibling-name\\:flex:is(:where(.peer\\/sibling-name)[aria-modal] ~ *) { - display: flex; - } - - .peer-aria-\\[valuenow\\=1\\]\\:flex:is(:where(.peer)[aria-valuenow="1"] ~ *) { - display: flex; - } - - .peer-aria-\\[valuenow\\=1\\]\\/sibling-name\\:flex:is(:where(.peer\\/sibling-name)[aria-valuenow="1"] ~ *) { - display: flex; - } - - .aria-checked\\:flex[aria-checked="true"] { - display: flex; - } - - .aria-\\[invalid\\=spelling\\]\\:flex[aria-invalid="spelling"] { - display: flex; - } - - .aria-\\[valuenow_\\=_\\"1\\"\\]\\:flex[aria-valuenow="1"] { - display: flex; - } - - .aria-\\[valuenow\\=1\\]\\:flex[aria-valuenow="1"] { - display: flex; - }" - `) - expect(await run(['aria-checked/foo:flex', 'aria-[invalid=spelling]/foo:flex'])).toEqual('') -}) - -test('data', async () => { - expect( - await run([ - 'data-disabled:flex', - 'data-[potato=salad]:flex', - 'data-[potato_=_"salad"]:flex', - 'data-[potato_^=_"salad"]:flex', - 'data-[potato="^_="]:flex', - 'data-[foo=1]:flex', - 'data-[foo=bar_baz]:flex', - "data-[foo$='bar'_i]:flex", - 'data-[foo$=bar_baz_i]:flex', - - 'group-data-[disabled]:flex', - 'group-data-[disabled]/parent-name:flex', - 'group-data-[foo=1]:flex', - 'group-data-[foo=1]/parent-name:flex', - 'group-data-[foo=bar baz]/parent-name:flex', - "group-data-[foo$='bar'_i]/parent-name:flex", - 'group-data-[foo$=bar_baz_i]/parent-name:flex', - - 'peer-data-[disabled]:flex', - 'peer-data-[disabled]/sibling-name:flex', - 'peer-data-[foo=1]:flex', - 'peer-data-[foo=1]/sibling-name:flex', - 'peer-data-[foo=bar baz]/sibling-name:flex', - "peer-data-[foo$='bar'_i]/sibling-name:flex", - 'peer-data-[foo$=bar_baz_i]/sibling-name:flex', - ]), - ).toMatchInlineSnapshot(` - ".group-data-\\[disabled\\]\\:flex:is(:where(.group)[data-disabled] *) { - display: flex; - } - - .group-data-\\[disabled\\]\\/parent-name\\:flex:is(:where(.group\\/parent-name)[data-disabled] *) { - display: flex; - } - - .group-data-\\[foo\\$\\=\\'bar\\'_i\\]\\/parent-name\\:flex:is(:where(.group\\/parent-name)[data-foo$="bar" i] *) { - display: flex; - } - - .group-data-\\[foo\\$\\=bar_baz_i\\]\\/parent-name\\:flex:is(:where(.group\\/parent-name)[data-foo$="bar baz" i] *) { - display: flex; - } - - .group-data-\\[foo\\=1\\]\\:flex:is(:where(.group)[data-foo="1"] *) { - display: flex; - } - - .group-data-\\[foo\\=1\\]\\/parent-name\\:flex:is(:where(.group\\/parent-name)[data-foo="1"] *) { - display: flex; - } - - .group-data-\\[foo\\=bar\\ baz\\]\\/parent-name\\:flex:is(:where(.group\\/parent-name)[data-foo="bar baz"] *) { - display: flex; - } - - .peer-data-\\[disabled\\]\\:flex:is(:where(.peer)[data-disabled] ~ *) { - display: flex; - } - - .peer-data-\\[disabled\\]\\/sibling-name\\:flex:is(:where(.peer\\/sibling-name)[data-disabled] ~ *) { - display: flex; - } - - .peer-data-\\[foo\\$\\=\\'bar\\'_i\\]\\/sibling-name\\:flex:is(:where(.peer\\/sibling-name)[data-foo$="bar" i] ~ *) { - display: flex; - } - - .peer-data-\\[foo\\$\\=bar_baz_i\\]\\/sibling-name\\:flex:is(:where(.peer\\/sibling-name)[data-foo$="bar baz" i] ~ *) { - display: flex; - } - - .peer-data-\\[foo\\=1\\]\\:flex:is(:where(.peer)[data-foo="1"] ~ *) { - display: flex; - } - - .peer-data-\\[foo\\=1\\]\\/sibling-name\\:flex:is(:where(.peer\\/sibling-name)[data-foo="1"] ~ *) { - display: flex; - } - - .peer-data-\\[foo\\=bar\\ baz\\]\\/sibling-name\\:flex:is(:where(.peer\\/sibling-name)[data-foo="bar baz"] ~ *) { - display: flex; - } - - .data-disabled\\:flex[data-disabled] { - display: flex; - } - - .data-\\[foo\\$\\=\\'bar\\'_i\\]\\:flex[data-foo$="bar" i] { - display: flex; - } - - .data-\\[foo\\$\\=bar_baz_i\\]\\:flex[data-foo$="bar baz" i] { - display: flex; - } - - .data-\\[foo\\=1\\]\\:flex[data-foo="1"] { - display: flex; - } - - .data-\\[foo\\=bar_baz\\]\\:flex[data-foo="bar baz"] { - display: flex; - } - - .data-\\[potato_\\=_\\"salad\\"\\]\\:flex[data-potato="salad"] { + 'peer-aria-[valuenow=1]:flex', + 'peer-aria-[modal]/sibling-name:flex', + 'peer-aria-checked/sibling-name:flex', + 'peer-aria-[valuenow=1]/sibling-name:flex', + ]), + ).toMatchInlineSnapshot(` + ".group-aria-checked\\:flex:is(:where(.group)[aria-checked="true"] *), .group-aria-checked\\/parent-name\\:flex:is(:where(.group\\/parent-name)[aria-checked="true"] *), .group-aria-\\[modal\\]\\:flex:is(:where(.group)[aria-modal] *), .group-aria-\\[modal\\]\\/parent-name\\:flex:is(:where(.group\\/parent-name)[aria-modal] *), .group-aria-\\[valuenow\\=1\\]\\:flex:is(:where(.group)[aria-valuenow="1"] *), .group-aria-\\[valuenow\\=1\\]\\/parent-name\\:flex:is(:where(.group\\/parent-name)[aria-valuenow="1"] *), .peer-aria-checked\\:flex:is(:where(.peer)[aria-checked="true"] ~ *), .peer-aria-checked\\/sibling-name\\:flex:is(:where(.peer\\/sibling-name)[aria-checked="true"] ~ *), .peer-aria-\\[modal\\]\\:flex:is(:where(.peer)[aria-modal] ~ *), .peer-aria-\\[modal\\]\\/sibling-name\\:flex:is(:where(.peer\\/sibling-name)[aria-modal] ~ *), .peer-aria-\\[valuenow\\=1\\]\\:flex:is(:where(.peer)[aria-valuenow="1"] ~ *), .peer-aria-\\[valuenow\\=1\\]\\/sibling-name\\:flex:is(:where(.peer\\/sibling-name)[aria-valuenow="1"] ~ *), .aria-checked\\:flex[aria-checked="true"], .aria-\\[invalid\\=spelling\\]\\:flex[aria-invalid="spelling"], .aria-\\[valuenow_\\=_\\"1\\"\\]\\:flex[aria-valuenow="1"], .aria-\\[valuenow\\=1\\]\\:flex[aria-valuenow="1"] { display: flex; - } + }" + `) + expect(await run(['aria-checked/foo:flex', 'aria-[invalid=spelling]/foo:flex'])).toEqual('') +}) - .data-\\[potato_\\^\\=_\\"salad\\"\\]\\:flex[data-potato^="salad"] { - display: flex; - } +test('data', async () => { + expect( + await run([ + 'data-disabled:flex', + 'data-[potato=salad]:flex', + 'data-[potato_=_"salad"]:flex', + 'data-[potato_^=_"salad"]:flex', + 'data-[potato="^_="]:flex', + 'data-[foo=1]:flex', + 'data-[foo=bar_baz]:flex', + "data-[foo$='bar'_i]:flex", + 'data-[foo$=bar_baz_i]:flex', - .data-\\[potato\\=\\"\\^_\\=\\"\\]\\:flex[data-potato="^ ="] { - display: flex; - } + 'group-data-[disabled]:flex', + 'group-data-[disabled]/parent-name:flex', + 'group-data-[foo=1]:flex', + 'group-data-[foo=1]/parent-name:flex', + 'group-data-[foo=bar baz]/parent-name:flex', + "group-data-[foo$='bar'_i]/parent-name:flex", + 'group-data-[foo$=bar_baz_i]/parent-name:flex', - .data-\\[potato\\=salad\\]\\:flex[data-potato="salad"] { + 'peer-data-[disabled]:flex', + 'peer-data-[disabled]/sibling-name:flex', + 'peer-data-[foo=1]:flex', + 'peer-data-[foo=1]/sibling-name:flex', + 'peer-data-[foo=bar baz]/sibling-name:flex', + "peer-data-[foo$='bar'_i]/sibling-name:flex", + 'peer-data-[foo$=bar_baz_i]/sibling-name:flex', + ]), + ).toMatchInlineSnapshot(` + ".group-data-\\[disabled\\]\\:flex:is(:where(.group)[data-disabled] *), .group-data-\\[disabled\\]\\/parent-name\\:flex:is(:where(.group\\/parent-name)[data-disabled] *), .group-data-\\[foo\\$\\=\\'bar\\'_i\\]\\/parent-name\\:flex:is(:where(.group\\/parent-name)[data-foo$="bar" i] *), .group-data-\\[foo\\$\\=bar_baz_i\\]\\/parent-name\\:flex:is(:where(.group\\/parent-name)[data-foo$="bar baz" i] *), .group-data-\\[foo\\=1\\]\\:flex:is(:where(.group)[data-foo="1"] *), .group-data-\\[foo\\=1\\]\\/parent-name\\:flex:is(:where(.group\\/parent-name)[data-foo="1"] *), .group-data-\\[foo\\=bar\\ baz\\]\\/parent-name\\:flex:is(:where(.group\\/parent-name)[data-foo="bar baz"] *), .peer-data-\\[disabled\\]\\:flex:is(:where(.peer)[data-disabled] ~ *), .peer-data-\\[disabled\\]\\/sibling-name\\:flex:is(:where(.peer\\/sibling-name)[data-disabled] ~ *), .peer-data-\\[foo\\$\\=\\'bar\\'_i\\]\\/sibling-name\\:flex:is(:where(.peer\\/sibling-name)[data-foo$="bar" i] ~ *), .peer-data-\\[foo\\$\\=bar_baz_i\\]\\/sibling-name\\:flex:is(:where(.peer\\/sibling-name)[data-foo$="bar baz" i] ~ *), .peer-data-\\[foo\\=1\\]\\:flex:is(:where(.peer)[data-foo="1"] ~ *), .peer-data-\\[foo\\=1\\]\\/sibling-name\\:flex:is(:where(.peer\\/sibling-name)[data-foo="1"] ~ *), .peer-data-\\[foo\\=bar\\ baz\\]\\/sibling-name\\:flex:is(:where(.peer\\/sibling-name)[data-foo="bar baz"] ~ *), .data-disabled\\:flex[data-disabled], .data-\\[foo\\$\\=\\'bar\\'_i\\]\\:flex[data-foo$="bar" i], .data-\\[foo\\$\\=bar_baz_i\\]\\:flex[data-foo$="bar baz" i], .data-\\[foo\\=1\\]\\:flex[data-foo="1"], .data-\\[foo\\=bar_baz\\]\\:flex[data-foo="bar baz"], .data-\\[potato_\\=_\\"salad\\"\\]\\:flex[data-potato="salad"], .data-\\[potato_\\^\\=_\\"salad\\"\\]\\:flex[data-potato^="salad"], .data-\\[potato\\=\\"\\^_\\=\\"\\]\\:flex[data-potato="^ ="], .data-\\[potato\\=salad\\]\\:flex[data-potato="salad"] { display: flex; }" `) @@ -2674,43 +1904,7 @@ test('nth', async () => { 'nth-last-of-type-[2n+1]:flex', ]), ).toMatchInlineSnapshot(` - ".nth-3\\:flex:nth-child(3) { - display: flex; - } - - .nth-\\[2n\\+1\\]\\:flex:nth-child(odd) { - display: flex; - } - - .nth-\\[2n\\+1_of_\\.foo\\]\\:flex:nth-child(odd of .foo) { - display: flex; - } - - .nth-last-3\\:flex:nth-last-child(3) { - display: flex; - } - - .nth-last-\\[2n\\+1\\]\\:flex:nth-last-child(odd) { - display: flex; - } - - .nth-last-\\[2n\\+1_of_\\.foo\\]\\:flex:nth-last-child(odd of .foo) { - display: flex; - } - - .nth-of-type-3\\:flex:nth-of-type(3) { - display: flex; - } - - .nth-of-type-\\[2n\\+1\\]\\:flex:nth-of-type(odd) { - display: flex; - } - - .nth-last-of-type-3\\:flex:nth-last-of-type(3) { - display: flex; - } - - .nth-last-of-type-\\[2n\\+1\\]\\:flex:nth-last-of-type(odd) { + ".nth-3\\:flex:nth-child(3), .nth-\\[2n\\+1\\]\\:flex:nth-child(odd), .nth-\\[2n\\+1_of_\\.foo\\]\\:flex:nth-child(odd of .foo), .nth-last-3\\:flex:nth-last-child(3), .nth-last-\\[2n\\+1\\]\\:flex:nth-last-child(odd), .nth-last-\\[2n\\+1_of_\\.foo\\]\\:flex:nth-last-child(odd of .foo), .nth-of-type-3\\:flex:nth-of-type(3), .nth-of-type-\\[2n\\+1\\]\\:flex:nth-of-type(odd), .nth-last-of-type-3\\:flex:nth-last-of-type(3), .nth-last-of-type-\\[2n\\+1\\]\\:flex:nth-last-of-type(odd) { display: flex; }" `) @@ -2799,25 +1993,13 @@ test('container queries', async () => { } @container (width >= 123px) { - .\\@\\[123px\\]\\:flex { - display: flex; - } - } - - @container (width >= 123px) { - .\\@min-\\[123px\\]\\:flex { - display: flex; - } - } - - @container name (width >= 456px) { - .\\@\\[456px\\]\\/name\\:flex { + .\\@\\[123px\\]\\:flex, .\\@min-\\[123px\\]\\:flex { display: flex; } } @container name (width >= 456px) { - .\\@min-\\[456px\\]\\/name\\:flex { + .\\@\\[456px\\]\\/name\\:flex, .\\@min-\\[456px\\]\\/name\\:flex { display: flex; } } @@ -2947,30 +2129,12 @@ test('variant order', async () => { } @media (hover: hover) { - .group-hover\\:flex:is(:where(.group):hover *) { - display: flex; - } - } - - @media (hover: hover) { - .peer-hover\\:flex:is(:where(.peer):hover ~ *) { + .group-hover\\:flex:is(:where(.group):hover *), .peer-hover\\:flex:is(:where(.peer):hover ~ *) { display: flex; } } - .first-letter\\:flex:first-letter { - display: flex; - } - - .first-line\\:flex:first-line { - display: flex; - } - - .marker\\:flex ::marker, .marker\\:flex::marker { - display: flex; - } - - .selection\\:flex ::selection, .selection\\:flex::selection { + .first-letter\\:flex:first-letter, .first-line\\:flex:first-line, .marker\\:flex ::marker, .marker\\:flex::marker, .selection\\:flex ::selection, .selection\\:flex::selection { display: flex; } @@ -2978,121 +2142,16 @@ test('variant order', async () => { display: flex; } - .placeholder\\:flex::placeholder { + .placeholder\\:flex::placeholder, .backdrop\\:flex::backdrop { display: flex; } - .backdrop\\:flex::backdrop { - display: flex; - } - - .before\\:flex:before { - content: var(--tw-content); - display: flex; - } - - .after\\:flex:after { + .before\\:flex:before, .after\\:flex:after { content: var(--tw-content); display: flex; } - .first\\:flex:first-child { - display: flex; - } - - .last\\:flex:last-child { - display: flex; - } - - .only\\:flex:only-child { - display: flex; - } - - .odd\\:flex:nth-child(odd) { - display: flex; - } - - .even\\:flex:nth-child(2n) { - display: flex; - } - - .first-of-type\\:flex:first-of-type { - display: flex; - } - - .last-of-type\\:flex:last-of-type { - display: flex; - } - - .only-of-type\\:flex:only-of-type { - display: flex; - } - - .visited\\:flex:visited { - display: flex; - } - - .target\\:flex:target { - display: flex; - } - - .open\\:flex:is([open], :popover-open) { - display: flex; - } - - .default\\:flex:default { - display: flex; - } - - .checked\\:flex:checked { - display: flex; - } - - .indeterminate\\:flex:indeterminate { - display: flex; - } - - .placeholder-shown\\:flex:placeholder-shown { - display: flex; - } - - .autofill\\:flex:autofill { - display: flex; - } - - .optional\\:flex:optional { - display: flex; - } - - .required\\:flex:required { - display: flex; - } - - .valid\\:flex:valid { - display: flex; - } - - .invalid\\:flex:invalid { - display: flex; - } - - .in-range\\:flex:in-range { - display: flex; - } - - .out-of-range\\:flex:out-of-range { - display: flex; - } - - .read-only\\:flex:read-only { - display: flex; - } - - .empty\\:flex:empty { - display: flex; - } - - .focus-within\\:flex:focus-within { + .first\\:flex:first-child, .last\\:flex:last-child, .only\\:flex:only-child, .odd\\:flex:nth-child(odd), .even\\:flex:nth-child(2n), .first-of-type\\:flex:first-of-type, .last-of-type\\:flex:last-of-type, .only-of-type\\:flex:only-of-type, .visited\\:flex:visited, .target\\:flex:target, .open\\:flex:is([open], :popover-open), .default\\:flex:default, .checked\\:flex:checked, .indeterminate\\:flex:indeterminate, .placeholder-shown\\:flex:placeholder-shown, .autofill\\:flex:autofill, .optional\\:flex:optional, .required\\:flex:required, .valid\\:flex:valid, .invalid\\:flex:invalid, .in-range\\:flex:in-range, .out-of-range\\:flex:out-of-range, .read-only\\:flex:read-only, .empty\\:flex:empty, .focus-within\\:flex:focus-within { display: flex; } @@ -3102,75 +2161,7 @@ test('variant order', async () => { } } - .focus\\:flex:focus { - display: flex; - } - - .focus-visible\\:flex:focus-visible { - display: flex; - } - - .active\\:flex:active { - display: flex; - } - - .enabled\\:flex:enabled { - display: flex; - } - - .disabled\\:flex:disabled { - display: flex; - } - - .has-\\[\\:hover\\]\\:flex:has(:hover) { - display: flex; - } - - .aria-busy\\:flex[aria-busy="true"] { - display: flex; - } - - .aria-checked\\:flex[aria-checked="true"] { - display: flex; - } - - .aria-disabled\\:flex[aria-disabled="true"] { - display: flex; - } - - .aria-expanded\\:flex[aria-expanded="true"] { - display: flex; - } - - .aria-hidden\\:flex[aria-hidden="true"] { - display: flex; - } - - .aria-pressed\\:flex[aria-pressed="true"] { - display: flex; - } - - .aria-readonly\\:flex[aria-readonly="true"] { - display: flex; - } - - .aria-required\\:flex[aria-required="true"] { - display: flex; - } - - .aria-selected\\:flex[aria-selected="true"] { - display: flex; - } - - .aria-\\[custom\\=true\\]\\:flex[aria-custom="true"] { - display: flex; - } - - .data-custom\\:flex[data-custom] { - display: flex; - } - - .data-\\[custom\\=true\\]\\:flex[data-custom="true"] { + .focus\\:flex:focus, .focus-visible\\:flex:focus-visible, .active\\:flex:active, .enabled\\:flex:enabled, .disabled\\:flex:disabled, .has-\\[\\:hover\\]\\:flex:has(:hover), .aria-busy\\:flex[aria-busy="true"], .aria-checked\\:flex[aria-checked="true"], .aria-disabled\\:flex[aria-disabled="true"], .aria-expanded\\:flex[aria-expanded="true"], .aria-hidden\\:flex[aria-hidden="true"], .aria-pressed\\:flex[aria-pressed="true"], .aria-readonly\\:flex[aria-readonly="true"], .aria-required\\:flex[aria-required="true"], .aria-selected\\:flex[aria-selected="true"], .aria-\\[custom\\=true\\]\\:flex[aria-custom="true"], .data-custom\\:flex[data-custom], .data-\\[custom\\=true\\]\\:flex[data-custom="true"] { display: flex; } @@ -3246,11 +2237,7 @@ test('variant order', async () => { } } - .ltr\\:flex:where(:dir(ltr), [dir="ltr"], [dir="ltr"] *) { - display: flex; - } - - .rtl\\:flex:where(:dir(rtl), [dir="rtl"], [dir="rtl"] *) { + .ltr\\:flex:where(:dir(ltr), [dir="ltr"], [dir="ltr"] *), .rtl\\:flex:where(:dir(rtl), [dir="rtl"], [dir="rtl"] *) { display: flex; } @@ -3317,28 +2304,8 @@ test('variants with the same root are sorted deterministically', async () => { let output = await compileCss('@tailwind utilities;', classList) expect(output.trim()).toEqual( - dedent(css` - .data-active\:flex[data-active] { - display: flex; - } - - .data-focus\:flex[data-focus] { - display: flex; - } - - .data-hover\:flex[data-hover] { - display: flex; - } - - .data-\[bar\]\:flex[data-bar] { - display: flex; - } - - .data-\[baz\]\:flex[data-baz] { - display: flex; - } - - .data-\[foo\]\:flex[data-foo] { + dedent(` + .data-active\\:flex[data-active], .data-focus\\:flex[data-focus], .data-hover\\:flex[data-hover], .data-\\[bar\\]\\:flex[data-bar], .data-\\[baz\\]\\:flex[data-baz], .data-\\[foo\\]\\:flex[data-foo] { display: flex; } `), @@ -3385,24 +2352,8 @@ test('matchVariant sorts deterministically', async () => { }) expect(output.trim()).toEqual( - dedent(css` - .is-data\:flex[data-default] { - display: flex; - } - - .is-data-foo\:flex[data-foo] { - display: flex; - } - - .is-data-bar\:flex[data-bar] { - display: flex; - } - - .is-data-\[potato\]\:flex[data-potato] { - display: flex; - } - - .is-data-\[sandwich\]\:flex[data-sandwich] { + dedent(` + .is-data\\:flex[data-default], .is-data-foo\\:flex[data-foo], .is-data-bar\\:flex[data-bar], .is-data-\\[potato\\]\\:flex[data-potato], .is-data-\\[sandwich\\]\\:flex[data-sandwich] { display: flex; } `), diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 65632719fbdc..d35c66ad88c1 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -7,5 +7,5 @@ packages: catalog: '@types/node': ^20.14.8 - lightningcss: ^1.26.0 + lightningcss: ^1.28.1 vite: ^5.4.0