Skip to content

Commit 3fe53dd

Browse files
Update changelog details and naming around the new not-* variant (tailwindlabs#14785)
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.
1 parent 430836f commit 3fe53dd

File tree

4 files changed

+52
-23
lines changed

4 files changed

+52
-23
lines changed

CHANGELOG.md

+4-3
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
### Added
1111

12-
- Added `not-*` versions of all builtin media query and supports variants ([#14743](https://github.com/tailwindlabs/tailwindcss/pull/14743))
13-
- Improved support for custom variants with `group-*`, `peer-*`, `has-*`, and `not-*` ([#14743](https://github.com/tailwindlabs/tailwindcss/pull/14743))
12+
- Support `not-*` with all built-in media query and `supports-*` variants ([#14743](https://github.com/tailwindlabs/tailwindcss/pull/14743))
13+
- Support `not-*` with custom variants containing at-rules ([#14743](https://github.com/tailwindlabs/tailwindcss/pull/14743))
14+
- Support `group-*`, `peer-*`, and `has-*` with custom variants containing multiple, non-nested style rules ([#14743](https://github.com/tailwindlabs/tailwindcss/pull/14743))
1415

1516
### Fixed
1617

1718
- Ensure individual logical property utilities are sorted later than left/right pair utilities ([#14777](https://github.com/tailwindlabs/tailwindcss/pull/14777))
1819
- Don't migrate important modifiers inside conditional statements in Vue and Alpine (e.g. `<div v-if="!border" />`) ([#14774](https://github.com/tailwindlabs/tailwindcss/pull/14774))
1920
- Ensure third-party plugins with `exports` in their `package.json` are resolved correctly ([#14775](https://github.com/tailwindlabs/tailwindcss/pull/14775))
2021
- Ensure underscores in the `url()` function are never unescaped ([#14776](https://github.com/tailwindlabs/tailwindcss/pull/14776))
21-
- Fixed display of complex variants in Intellisense ([#14743](https://github.com/tailwindlabs/tailwindcss/pull/14743))
22+
- Ensure complex variants are displayed correctly in IntelliSense completions ([#14743](https://github.com/tailwindlabs/tailwindcss/pull/14743))
2223
- _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))
2324
- _Upgrade (experimental)_: Only generate Preflight compatibility styles when Preflight is used ([#14773](https://github.com/tailwindlabs/tailwindcss/pull/14773))
2425
- _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))

packages/tailwindcss/src/candidate.test.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ it('should parse compound variants with an arbitrary value as an arbitrary varia
209209
utilities.static('flex', () => [])
210210

211211
let variants = new Variants()
212-
variants.compoundWith('group', Compounds.StyleRules, () => {})
212+
variants.compound('group', Compounds.StyleRules, () => {})
213213

214214
expect(run('group-[&_p]/parent-name:flex', { utilities, variants })).toMatchInlineSnapshot(`
215215
[
@@ -244,7 +244,7 @@ it('should parse a simple utility with a parameterized variant and a modifier',
244244
utilities.static('flex', () => [])
245245

246246
let variants = new Variants()
247-
variants.compoundWith('group', Compounds.StyleRules, () => {})
247+
variants.compound('group', Compounds.StyleRules, () => {})
248248
variants.functional('aria', () => {})
249249

250250
expect(run('group-aria-[disabled]/parent-name:flex', { utilities, variants }))
@@ -286,7 +286,7 @@ it('should parse compound group with itself group-group-*', () => {
286286

287287
let variants = new Variants()
288288
variants.static('hover', () => {})
289-
variants.compoundWith('group', Compounds.StyleRules, () => {})
289+
variants.compound('group', Compounds.StyleRules, () => {})
290290

291291
expect(run('group-group-group-hover/parent-name:flex', { utilities, variants }))
292292
.toMatchInlineSnapshot(`
@@ -1255,7 +1255,7 @@ it('should not parse compound group with a non-compoundable variant', () => {
12551255
utilities.static('flex', () => [])
12561256

12571257
let variants = new Variants()
1258-
variants.compoundWith('group', Compounds.StyleRules, () => {})
1258+
variants.compound('group', Compounds.StyleRules, () => {})
12591259

12601260
expect(run('group-*:flex', { utilities, variants })).toMatchInlineSnapshot(`[]`)
12611261
})

packages/tailwindcss/src/variants.test.ts

+32-8
Original file line numberDiff line numberDiff line change
@@ -1706,6 +1706,10 @@ test('not', async () => {
17061706
`,
17071707
[
17081708
'not-[:checked]:flex',
1709+
'not-[@media_print]:flex',
1710+
'not-[@media(orientation:portrait)]:flex',
1711+
'not-[@media_(orientation:landscape)]:flex',
1712+
'not-[@media_not_(orientation:portrait)]:flex',
17091713
'not-hocus:flex',
17101714
'not-device-hocus:flex',
17111715

@@ -2052,6 +2056,30 @@ test('not', async () => {
20522056
display: flex;
20532057
}
20542058
2059+
@media not (orientation: landscape) {
2060+
.not-\\[\\@media_\\(orientation\\:landscape\\)\\]\\:flex {
2061+
display: flex;
2062+
}
2063+
}
2064+
2065+
@media (orientation: portrait) {
2066+
.not-\\[\\@media_not_\\(orientation\\:portrait\\)\\]\\:flex {
2067+
display: flex;
2068+
}
2069+
}
2070+
2071+
@media not print {
2072+
.not-\\[\\@media_print\\]\\:flex {
2073+
display: flex;
2074+
}
2075+
}
2076+
2077+
@media not (orientation: portrait) {
2078+
.not-\\[\\@media\\(orientation\\:portrait\\)\\]\\:flex {
2079+
display: flex;
2080+
}
2081+
}
2082+
20552083
.group-not-checked\\:flex:is(:where(.group):not(:checked) *) {
20562084
display: flex;
20572085
}
@@ -2122,6 +2150,10 @@ test('not', async () => {
21222150
'not-[+img]:flex',
21232151
'not-[~img]:flex',
21242152
'not-[:checked]/foo:flex',
2153+
'not-[@media_screen,print]:flex',
2154+
'not-[@media_not_screen,print]:flex',
2155+
'not-[@media_not_screen,not_print]:flex',
2156+
21252157
'not-nested-at-rules:flex',
21262158
'not-nested-style-rules:flex',
21272159
'not-multiple-media-conditions:flex',
@@ -2147,14 +2179,6 @@ test('not', async () => {
21472179

21482180
// This is not a conditional at rule
21492181
'not-starting:flex',
2150-
2151-
// TODO:
2152-
// 'not-group-[...]:flex',
2153-
// 'not-group-*:flex',
2154-
// 'not-peer-[...]:flex',
2155-
// 'not-peer-*:flex',
2156-
// 'not-max-*:flex',
2157-
// 'not-min-*:flex',
21582182
],
21592183
),
21602184
).toEqual('')

packages/tailwindcss/src/variants.ts

+12-8
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ export class Variants {
101101
})
102102
}
103103

104-
compoundWith(
104+
compound(
105105
name: string,
106106
compoundsWith: Compounds,
107107
applyFn: VariantFn<'compound'>,
@@ -354,12 +354,16 @@ export function createVariants(theme: Theme): Variants {
354354
})
355355
}
356356

357+
let conditionalRules = ['@media', '@supports', '@container']
358+
357359
function negateSelector(selector: string) {
358360
if (selector[0] === '@') {
359-
let name = selector.slice(1, selector.indexOf(' '))
360-
let params = selector.slice(selector.indexOf(' ') + 1)
361+
for (let ruleName of conditionalRules) {
362+
if (!selector.startsWith(ruleName)) continue
363+
364+
let name = ruleName.slice(1)
365+
let params = selector.slice(ruleName.length).trim()
361366

362-
if (name === 'media' || name === 'supports' || name === 'container') {
363367
let conditions = segment(params, ',')
364368

365369
// We don't support things like `@media screen, print` because
@@ -392,7 +396,7 @@ export function createVariants(theme: Theme): Variants {
392396
return `&:not(${selectors.join(', ')})`
393397
}
394398

395-
variants.compoundWith('not', Compounds.StyleRules | Compounds.AtRules, (ruleNode, variant) => {
399+
variants.compound('not', Compounds.StyleRules | Compounds.AtRules, (ruleNode, variant) => {
396400
if (variant.variant.kind === 'arbitrary' && variant.variant.relative) return null
397401

398402
if (variant.modifier) return null
@@ -467,7 +471,7 @@ export function createVariants(theme: Theme): Variants {
467471
})
468472
})
469473

470-
variants.compoundWith('group', Compounds.StyleRules, (ruleNode, variant) => {
474+
variants.compound('group', Compounds.StyleRules, (ruleNode, variant) => {
471475
if (variant.variant.kind === 'arbitrary' && variant.variant.relative) return null
472476

473477
// Name the group by appending the modifier to `group` class itself if
@@ -523,7 +527,7 @@ export function createVariants(theme: Theme): Variants {
523527
})
524528
})
525529

526-
variants.compoundWith('peer', Compounds.StyleRules, (ruleNode, variant) => {
530+
variants.compound('peer', Compounds.StyleRules, (ruleNode, variant) => {
527531
if (variant.variant.kind === 'arbitrary' && variant.variant.relative) return null
528532

529533
// Name the peer by appending the modifier to `peer` class itself if
@@ -670,7 +674,7 @@ export function createVariants(theme: Theme): Variants {
670674

671675
staticVariant('inert', ['&:is([inert], [inert] *)'])
672676

673-
variants.compoundWith('has', Compounds.StyleRules, (ruleNode, variant) => {
677+
variants.compound('has', Compounds.StyleRules, (ruleNode, variant) => {
674678
if (variant.modifier) return null
675679

676680
let didApply = false

0 commit comments

Comments
 (0)