From 3fe53dd8f08dd4d5af60304a2872cacbd7dd837a Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Thu, 24 Oct 2024 14:50:20 -0400 Subject: [PATCH] Update changelog details and naming around the new `not-*` variant (#14785) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I've tweaked the changelog with suggestions from @adamwathan to improve clarity around what the actual changes are. I also renamed `compoundWith` back to `compound` — I felt that it made sense at the time but keeping the old name definitely feels better the more I think about it. --- CHANGELOG.md | 7 ++-- packages/tailwindcss/src/candidate.test.ts | 8 ++--- packages/tailwindcss/src/variants.test.ts | 40 +++++++++++++++++----- packages/tailwindcss/src/variants.ts | 20 ++++++----- 4 files changed, 52 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 11c868d14..f0d5b25d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,8 +9,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- Added `not-*` versions of all builtin media query and supports variants ([#14743](https://github.com/tailwindlabs/tailwindcss/pull/14743)) -- Improved support for custom variants with `group-*`, `peer-*`, `has-*`, and `not-*` ([#14743](https://github.com/tailwindlabs/tailwindcss/pull/14743)) +- Support `not-*` with all built-in media query and `supports-*` variants ([#14743](https://github.com/tailwindlabs/tailwindcss/pull/14743)) +- Support `not-*` with custom variants containing at-rules ([#14743](https://github.com/tailwindlabs/tailwindcss/pull/14743)) +- Support `group-*`, `peer-*`, and `has-*` with custom variants containing multiple, non-nested style rules ([#14743](https://github.com/tailwindlabs/tailwindcss/pull/14743)) ### Fixed @@ -18,7 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Don't migrate important modifiers inside conditional statements in Vue and Alpine (e.g. `
`) ([#14774](https://github.com/tailwindlabs/tailwindcss/pull/14774)) - Ensure third-party plugins with `exports` in their `package.json` are resolved correctly ([#14775](https://github.com/tailwindlabs/tailwindcss/pull/14775)) - Ensure underscores in the `url()` function are never unescaped ([#14776](https://github.com/tailwindlabs/tailwindcss/pull/14776)) -- Fixed display of complex variants in Intellisense ([#14743](https://github.com/tailwindlabs/tailwindcss/pull/14743)) +- Ensure complex variants are displayed correctly in IntelliSense completions ([#14743](https://github.com/tailwindlabs/tailwindcss/pull/14743)) - _Upgrade (experimental)_: Ensure `@import` statements for relative CSS files are actually migrated to use relative path syntax ([#14769](https://github.com/tailwindlabs/tailwindcss/pull/14769)) - _Upgrade (experimental)_: Only generate Preflight compatibility styles when Preflight is used ([#14773](https://github.com/tailwindlabs/tailwindcss/pull/14773)) - _Upgrade (experimental)_: Don't escape underscores when printing theme values migrated to CSS variables in arbitrary values (e.g. `m-[var(--spacing-1_5)]` instead of `m-[var(--spacing-1\_5)]`) ([#14778](https://github.com/tailwindlabs/tailwindcss/pull/14778)) diff --git a/packages/tailwindcss/src/candidate.test.ts b/packages/tailwindcss/src/candidate.test.ts index 568326bb6..9837e3471 100644 --- a/packages/tailwindcss/src/candidate.test.ts +++ b/packages/tailwindcss/src/candidate.test.ts @@ -209,7 +209,7 @@ it('should parse compound variants with an arbitrary value as an arbitrary varia utilities.static('flex', () => []) let variants = new Variants() - variants.compoundWith('group', Compounds.StyleRules, () => {}) + variants.compound('group', Compounds.StyleRules, () => {}) expect(run('group-[&_p]/parent-name:flex', { utilities, variants })).toMatchInlineSnapshot(` [ @@ -244,7 +244,7 @@ it('should parse a simple utility with a parameterized variant and a modifier', utilities.static('flex', () => []) let variants = new Variants() - variants.compoundWith('group', Compounds.StyleRules, () => {}) + variants.compound('group', Compounds.StyleRules, () => {}) variants.functional('aria', () => {}) expect(run('group-aria-[disabled]/parent-name:flex', { utilities, variants })) @@ -286,7 +286,7 @@ it('should parse compound group with itself group-group-*', () => { let variants = new Variants() variants.static('hover', () => {}) - variants.compoundWith('group', Compounds.StyleRules, () => {}) + variants.compound('group', Compounds.StyleRules, () => {}) expect(run('group-group-group-hover/parent-name:flex', { utilities, variants })) .toMatchInlineSnapshot(` @@ -1255,7 +1255,7 @@ it('should not parse compound group with a non-compoundable variant', () => { utilities.static('flex', () => []) let variants = new Variants() - variants.compoundWith('group', Compounds.StyleRules, () => {}) + variants.compound('group', Compounds.StyleRules, () => {}) expect(run('group-*:flex', { utilities, variants })).toMatchInlineSnapshot(`[]`) }) diff --git a/packages/tailwindcss/src/variants.test.ts b/packages/tailwindcss/src/variants.test.ts index a6c8a4d7f..e154255d8 100644 --- a/packages/tailwindcss/src/variants.test.ts +++ b/packages/tailwindcss/src/variants.test.ts @@ -1706,6 +1706,10 @@ test('not', async () => { `, [ 'not-[:checked]:flex', + 'not-[@media_print]:flex', + 'not-[@media(orientation:portrait)]:flex', + 'not-[@media_(orientation:landscape)]:flex', + 'not-[@media_not_(orientation:portrait)]:flex', 'not-hocus:flex', 'not-device-hocus:flex', @@ -2052,6 +2056,30 @@ test('not', async () => { display: flex; } + @media not (orientation: landscape) { + .not-\\[\\@media_\\(orientation\\:landscape\\)\\]\\:flex { + display: flex; + } + } + + @media (orientation: portrait) { + .not-\\[\\@media_not_\\(orientation\\:portrait\\)\\]\\:flex { + display: flex; + } + } + + @media not print { + .not-\\[\\@media_print\\]\\:flex { + display: flex; + } + } + + @media not (orientation: portrait) { + .not-\\[\\@media\\(orientation\\:portrait\\)\\]\\:flex { + display: flex; + } + } + .group-not-checked\\:flex:is(:where(.group):not(:checked) *) { display: flex; } @@ -2122,6 +2150,10 @@ test('not', async () => { 'not-[+img]:flex', 'not-[~img]:flex', 'not-[:checked]/foo:flex', + 'not-[@media_screen,print]:flex', + 'not-[@media_not_screen,print]:flex', + 'not-[@media_not_screen,not_print]:flex', + 'not-nested-at-rules:flex', 'not-nested-style-rules:flex', 'not-multiple-media-conditions:flex', @@ -2147,14 +2179,6 @@ test('not', async () => { // This is not a conditional at rule 'not-starting:flex', - - // TODO: - // 'not-group-[...]:flex', - // 'not-group-*:flex', - // 'not-peer-[...]:flex', - // 'not-peer-*:flex', - // 'not-max-*:flex', - // 'not-min-*:flex', ], ), ).toEqual('') diff --git a/packages/tailwindcss/src/variants.ts b/packages/tailwindcss/src/variants.ts index 39c089eb4..a51a06a38 100644 --- a/packages/tailwindcss/src/variants.ts +++ b/packages/tailwindcss/src/variants.ts @@ -101,7 +101,7 @@ export class Variants { }) } - compoundWith( + compound( name: string, compoundsWith: Compounds, applyFn: VariantFn<'compound'>, @@ -354,12 +354,16 @@ export function createVariants(theme: Theme): Variants { }) } + let conditionalRules = ['@media', '@supports', '@container'] + function negateSelector(selector: string) { if (selector[0] === '@') { - let name = selector.slice(1, selector.indexOf(' ')) - let params = selector.slice(selector.indexOf(' ') + 1) + for (let ruleName of conditionalRules) { + if (!selector.startsWith(ruleName)) continue + + let name = ruleName.slice(1) + let params = selector.slice(ruleName.length).trim() - if (name === 'media' || name === 'supports' || name === 'container') { let conditions = segment(params, ',') // We don't support things like `@media screen, print` because @@ -392,7 +396,7 @@ export function createVariants(theme: Theme): Variants { return `&:not(${selectors.join(', ')})` } - variants.compoundWith('not', Compounds.StyleRules | Compounds.AtRules, (ruleNode, variant) => { + variants.compound('not', Compounds.StyleRules | Compounds.AtRules, (ruleNode, variant) => { if (variant.variant.kind === 'arbitrary' && variant.variant.relative) return null if (variant.modifier) return null @@ -467,7 +471,7 @@ export function createVariants(theme: Theme): Variants { }) }) - variants.compoundWith('group', Compounds.StyleRules, (ruleNode, variant) => { + variants.compound('group', Compounds.StyleRules, (ruleNode, variant) => { if (variant.variant.kind === 'arbitrary' && variant.variant.relative) return null // Name the group by appending the modifier to `group` class itself if @@ -523,7 +527,7 @@ export function createVariants(theme: Theme): Variants { }) }) - variants.compoundWith('peer', Compounds.StyleRules, (ruleNode, variant) => { + variants.compound('peer', Compounds.StyleRules, (ruleNode, variant) => { if (variant.variant.kind === 'arbitrary' && variant.variant.relative) return null // Name the peer by appending the modifier to `peer` class itself if @@ -670,7 +674,7 @@ export function createVariants(theme: Theme): Variants { staticVariant('inert', ['&:is([inert], [inert] *)']) - variants.compoundWith('has', Compounds.StyleRules, (ruleNode, variant) => { + variants.compound('has', Compounds.StyleRules, (ruleNode, variant) => { if (variant.modifier) return null let didApply = false