Skip to content

Commit 36c880a

Browse files
authored
Improve before and after variants (#5820)
* remove unused `withRule` * ensure all ::before and ::after elements have content * update --tw-content for the content plugin * simplify `before` and `after` variants * update tests, to reflect changes * make new `format` and `wrap` API's private for now * allow returning a format string from `addVariant` callback * add `content: var(--tw-content)` for before/after variants * update tests to add `content: var(--tw-content)` * update changelog
1 parent f12c0e1 commit 36c880a

12 files changed

+69
-63
lines changed

CHANGELOG.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010
### Changed
1111

1212
- Don't use pointer cursor on disabled buttons by default ([#5772](https://github.com/tailwindlabs/tailwindcss/pull/5772))
13-
- Improve `addVariant` API ([#5809](https://github.com/tailwindlabs/tailwindcss/pull/5809))
13+
- Set default content value in preflight instead of within each before/after utility ([#5820](https://github.com/tailwindlabs/tailwindcss/pull/5820))
1414

1515
### Added
1616

@@ -21,11 +21,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2121
- Add all standard `cursor-*` values by default ([#5734](https://github.com/tailwindlabs/tailwindcss/pull/5734))
2222
- Add `grow-*` and `shrink-*` utilities, deprecate `flex-grow-*` and `flex-shrink-*` ([#5733](https://github.com/tailwindlabs/tailwindcss/pull/5733))
2323
- Add `text-decoration-color` utilities ([#5760](https://github.com/tailwindlabs/tailwindcss/pull/5760))
24+
- Add declarative `addVariant` syntax ([#5809](https://github.com/tailwindlabs/tailwindcss/pull/5809))
2425

2526
### Fixed
2627

2728
- Configure chokidar's `awaitWriteFinish` setting to avoid occasional stale builds on Windows ([#5774](https://github.com/tailwindlabs/tailwindcss/pull/5774))
2829
- Fix CLI `--content` option ([#5775](https://github.com/tailwindlabs/tailwindcss/pull/5775))
30+
- Fix before/after utilities overriding custom content values at larger breakpoints ([#5820](https://github.com/tailwindlabs/tailwindcss/pull/5820))
2931

3032
## [3.0.0-alpha.1] - 2021-10-01
3133

src/corePlugins.js

+18-19
Original file line numberDiff line numberDiff line change
@@ -22,37 +22,34 @@ export let variantPlugins = {
2222

2323
addVariant('file', '&::file-selector-button')
2424

25-
// TODO: Use `addVariant('before', '*::before')` instead, once `content`
26-
// fix is implemented.
27-
addVariant('before', ({ format, withRule }) => {
28-
format('&::before')
29-
30-
withRule((rule) => {
25+
addVariant('before', ({ container }) => {
26+
container.walkRules((rule) => {
3127
let foundContent = false
3228
rule.walkDecls('content', () => {
3329
foundContent = true
3430
})
31+
3532
if (!foundContent) {
36-
rule.prepend(postcss.decl({ prop: 'content', value: '""' }))
33+
rule.prepend(postcss.decl({ prop: 'content', value: 'var(--tw-content)' }))
3734
}
3835
})
39-
})
4036

41-
// TODO: Use `addVariant('after', '*::after')` instead, once `content`
42-
// fix is implemented.
43-
addVariant('after', ({ format, withRule }) => {
44-
format('&::after')
37+
return '&::before'
38+
})
4539

46-
withRule((rule) => {
40+
addVariant('after', ({ container }) => {
41+
container.walkRules((rule) => {
4742
let foundContent = false
4843
rule.walkDecls('content', () => {
4944
foundContent = true
5045
})
5146

5247
if (!foundContent) {
53-
rule.prepend(postcss.decl({ prop: 'content', value: '""' }))
48+
rule.prepend(postcss.decl({ prop: 'content', value: 'var(--tw-content)' }))
5449
}
5550
})
51+
52+
return '&::after'
5653
})
5754
},
5855

@@ -112,22 +109,22 @@ export let variantPlugins = {
112109
},
113110

114111
directionVariants: ({ addVariant }) => {
115-
addVariant('ltr', ({ format }) => {
112+
addVariant('ltr', () => {
116113
log.warn('rtl-experimental', [
117114
'The RTL features in Tailwind CSS are currently in preview.',
118115
'Preview features are not covered by semver, and may be improved in breaking ways at any time.',
119116
])
120117

121-
format('[dir="ltr"] &')
118+
return '[dir="ltr"] &'
122119
})
123120

124-
addVariant('rtl', ({ format }) => {
121+
addVariant('rtl', () => {
125122
log.warn('rtl-experimental', [
126123
'The RTL features in Tailwind CSS are currently in preview.',
127124
'Preview features are not covered by semver, and may be improved in breaking ways at any time.',
128125
])
129126

130-
format('[dir="rtl"] &')
127+
return '[dir="rtl"] &'
131128
})
132129
},
133130

@@ -2265,5 +2262,7 @@ export let corePlugins = {
22652262
{ filterDefault: true }
22662263
),
22672264
willChange: createUtilityPlugin('willChange', [['will-change', ['will-change']]]),
2268-
content: createUtilityPlugin('content'),
2265+
content: createUtilityPlugin('content', [
2266+
['content', ['--tw-content', ['content', 'var(--tw-content)']]],
2267+
]),
22692268
}

src/css/preflight.css

+5
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@
1212
border-color: currentColor; /* 2 */
1313
}
1414

15+
::before,
16+
::after {
17+
--tw-content: '';
18+
}
19+
1520
/*
1621
1. Use a consistent sensible line-height in all browsers.
1722
2. Prevent adjustments of font size after orientation changes in iOS.

src/lib/generateRules.js

+7-3
Original file line numberDiff line numberDiff line change
@@ -143,26 +143,30 @@ function applyVariant(variant, matches, context) {
143143
}
144144

145145
let ruleWithVariant = variantFunction({
146+
// Public API
146147
get container() {
147148
prepareBackup()
148149
return clone
149150
},
150151
separator: context.tailwindConfig.separator,
151152
modifySelectors,
153+
154+
// Private API for now
152155
wrap(wrapper) {
153156
let nodes = clone.nodes
154157
clone.removeAll()
155158
wrapper.append(nodes)
156159
clone.append(wrapper)
157160
},
158-
withRule(modify) {
159-
clone.walkRules(modify)
160-
},
161161
format(selectorFormat) {
162162
collectedFormats.push(selectorFormat)
163163
},
164164
})
165165

166+
if (typeof ruleWithVariant === 'string') {
167+
collectedFormats.push(ruleWithVariant)
168+
}
169+
166170
if (ruleWithVariant === null) {
167171
continue
168172
}

src/lib/setupContextUtils.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,10 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
217217
addVariant(variantName, variantFunctions, options = {}) {
218218
variantFunctions = [].concat(variantFunctions).map((variantFunction) => {
219219
if (typeof variantFunction !== 'string') {
220-
return variantFunction
220+
// Safelist public API functions
221+
return ({ modifySelectors, container, separator }) => {
222+
return variantFunction({ modifySelectors, container, separator })
223+
}
221224
}
222225

223226
variantFunction = variantFunction

tests/arbitrary-values.test.css

+6-3
Original file line numberDiff line numberDiff line change
@@ -1011,13 +1011,16 @@
10111011
will-change: var(--will-change);
10121012
}
10131013
.content-\[\'hello\'\] {
1014-
content: 'hello';
1014+
--tw-content: 'hello';
1015+
content: var(--tw-content);
10151016
}
10161017
.content-\[attr\(content-before\)\] {
1017-
content: attr(content-before);
1018+
--tw-content: attr(content-before);
1019+
content: var(--tw-content);
10181020
}
10191021
.content-\[\'\>\'\] {
1020-
content: '>';
1022+
--tw-content: '>';
1023+
content: var(--tw-content);
10211024
}
10221025
@media (min-width: 1024px) {
10231026
.lg\:grid-cols-\[200px\2c repeat\(auto-fill\2c minmax\(15\%\2c 100px\)\)\2c 300px\] {

tests/arbitrary-values.test.js

+8-4
Original file line numberDiff line numberDiff line change
@@ -176,15 +176,18 @@ it('should convert _ to spaces', () => {
176176
}
177177
178178
.content-\\[_hello_world_\\] {
179-
content: hello world;
179+
--tw-content: hello world;
180+
content: var(--tw-content);
180181
}
181182
182183
.content-\\[___abc____\\] {
183-
content: abc;
184+
--tw-content: abc;
185+
content: var(--tw-content);
184186
}
185187
186188
.content-\\[\\'__hello__world__\\'\\] {
187-
content: ' hello world ';
189+
--tw-content: ' hello world ';
190+
content: var(--tw-content);
188191
}
189192
`)
190193
})
@@ -199,7 +202,8 @@ it('should not convert escaped underscores with spaces', () => {
199202
return run('@tailwind utilities', config).then((result) => {
200203
return expect(result.css).toMatchFormattedCss(css`
201204
.content-\[\'snake\\_case\'\] {
202-
content: 'snake_case';
205+
--tw-content: 'snake_case';
206+
content: var(--tw-content);
203207
}
204208
`)
205209
})

tests/basic-usage.test.css

+2-1
Original file line numberDiff line numberDiff line change
@@ -968,5 +968,6 @@
968968
will-change: transform;
969969
}
970970
.content-none {
971-
content: none;
971+
--tw-content: none;
972+
content: var(--tw-content);
972973
}

tests/extractor-edge-cases.test.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ test('arbitrary values with quotes', async () => {
2222
return run('@tailwind utilities', config).then((result) => {
2323
expect(result.css).toMatchFormattedCss(css`
2424
.content-\[\'hello\]\'\] {
25-
content: 'hello]';
25+
--tw-content: 'hello]';
26+
content: var(--tw-content);
2627
}
2728
`)
2829
})

tests/resolve-defaults-at-rules.test.js

+7-17
Original file line numberDiff line numberDiff line change
@@ -121,12 +121,12 @@ test('with pseudo-element variants', async () => {
121121
}
122122
/* --- */
123123
.before\:scale-x-110::before {
124-
content: '';
124+
content: var(--tw-content);
125125
--tw-scale-x: 1.1;
126126
transform: var(--tw-transform);
127127
}
128128
.after\:rotate-3::after {
129-
content: '';
129+
content: var(--tw-content);
130130
--tw-rotate: 3deg;
131131
transform: var(--tw-transform);
132132
}
@@ -205,12 +205,12 @@ test('with multi-class pseudo-element variants', async () => {
205205
}
206206
/* --- */
207207
.group:hover .group-hover\:before\:scale-x-110::before {
208-
content: '';
208+
content: var(--tw-content);
209209
--tw-scale-x: 1.1;
210210
transform: var(--tw-transform);
211211
}
212212
.peer:focus ~ .peer-focus\:after\:rotate-3::after {
213-
content: '';
213+
content: var(--tw-content);
214214
--tw-rotate: 3deg;
215215
transform: var(--tw-transform);
216216
}
@@ -253,12 +253,12 @@ test('with multi-class pseudo-element and pseudo-class variants', async () => {
253253
}
254254
/* --- */
255255
.group:hover .group-hover\:hover\:before\:scale-x-110::before:hover {
256-
content: '';
256+
content: var(--tw-content);
257257
--tw-scale-x: 1.1;
258258
transform: var(--tw-transform);
259259
}
260260
.peer:focus ~ .peer-focus\:focus\:after\:rotate-3::after:focus {
261-
content: '';
261+
content: var(--tw-content);
262262
--tw-rotate: 3deg;
263263
transform: var(--tw-transform);
264264
}
@@ -288,7 +288,6 @@ test('with apply', async () => {
288288
}
289289
290290
.baz::before {
291-
content: '';
292291
@apply rotate-45;
293292
}
294293
@@ -351,13 +350,12 @@ test('with apply', async () => {
351350
transform: var(--tw-transform);
352351
}
353352
.bar::before {
354-
content: '';
353+
content: var(--tw-content);
355354
--tw-scale-x: 1.1;
356355
--tw-scale-y: 1.1;
357356
transform: var(--tw-transform);
358357
}
359358
.baz::before {
360-
content: '';
361359
--tw-rotate: 45deg;
362360
transform: var(--tw-transform);
363361
}
@@ -408,22 +406,18 @@ test('legacy pseudo-element syntax is supported', async () => {
408406
@tailwind utilities;
409407
410408
.a:before {
411-
content: '';
412409
@apply rotate-45;
413410
}
414411
415412
.b:after {
416-
content: '';
417413
@apply rotate-3;
418414
}
419415
420416
.c:first-line {
421-
content: '';
422417
@apply rotate-1;
423418
}
424419
425420
.d:first-letter {
426-
content: '';
427421
@apply rotate-6;
428422
}
429423
`
@@ -447,22 +441,18 @@ test('legacy pseudo-element syntax is supported', async () => {
447441
}
448442
/* --- */
449443
.a:before {
450-
content: '';
451444
--tw-rotate: 45deg;
452445
transform: var(--tw-transform);
453446
}
454447
.b:after {
455-
content: '';
456448
--tw-rotate: 3deg;
457449
transform: var(--tw-transform);
458450
}
459451
.c:first-line {
460-
content: '';
461452
--tw-rotate: 1deg;
462453
transform: var(--tw-transform);
463454
}
464455
.d:first-letter {
465-
content: '';
466456
--tw-rotate: 6deg;
467457
transform: var(--tw-transform);
468458
}

tests/variants.test.css

+4-4
Original file line numberDiff line numberDiff line change
@@ -165,20 +165,20 @@
165165
color: rgb(255 255 255 / var(--tw-text-opacity));
166166
}
167167
.before\:block::before {
168-
content: '';
168+
content: var(--tw-content);
169169
display: block;
170170
}
171171
.before\:bg-red-500::before {
172-
content: '';
172+
content: var(--tw-content);
173173
--tw-bg-opacity: 1;
174174
background-color: rgb(239 68 68 / var(--tw-bg-opacity));
175175
}
176176
.after\:flex::after {
177-
content: '';
177+
content: var(--tw-content);
178178
display: flex;
179179
}
180180
.after\:uppercase::after {
181-
content: '';
181+
content: var(--tw-content);
182182
text-transform: uppercase;
183183
}
184184
.first\:shadow-md:first-child {

0 commit comments

Comments
 (0)