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
This commit is contained in:
parent
f12c0e1fa5
commit
36c880abab
12 changed files with 69 additions and 63 deletions
|
|
@ -10,7 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
### Changed
|
||||
|
||||
- Don't use pointer cursor on disabled buttons by default ([#5772](https://github.com/tailwindlabs/tailwindcss/pull/5772))
|
||||
- Improve `addVariant` API ([#5809](https://github.com/tailwindlabs/tailwindcss/pull/5809))
|
||||
- Set default content value in preflight instead of within each before/after utility ([#5820](https://github.com/tailwindlabs/tailwindcss/pull/5820))
|
||||
|
||||
### Added
|
||||
|
||||
|
|
@ -21,11 +21,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- Add all standard `cursor-*` values by default ([#5734](https://github.com/tailwindlabs/tailwindcss/pull/5734))
|
||||
- Add `grow-*` and `shrink-*` utilities, deprecate `flex-grow-*` and `flex-shrink-*` ([#5733](https://github.com/tailwindlabs/tailwindcss/pull/5733))
|
||||
- Add `text-decoration-color` utilities ([#5760](https://github.com/tailwindlabs/tailwindcss/pull/5760))
|
||||
- Add declarative `addVariant` syntax ([#5809](https://github.com/tailwindlabs/tailwindcss/pull/5809))
|
||||
|
||||
### Fixed
|
||||
|
||||
- Configure chokidar's `awaitWriteFinish` setting to avoid occasional stale builds on Windows ([#5774](https://github.com/tailwindlabs/tailwindcss/pull/5774))
|
||||
- Fix CLI `--content` option ([#5775](https://github.com/tailwindlabs/tailwindcss/pull/5775))
|
||||
- Fix before/after utilities overriding custom content values at larger breakpoints ([#5820](https://github.com/tailwindlabs/tailwindcss/pull/5820))
|
||||
|
||||
## [3.0.0-alpha.1] - 2021-10-01
|
||||
|
||||
|
|
|
|||
|
|
@ -22,37 +22,34 @@ export let variantPlugins = {
|
|||
|
||||
addVariant('file', '&::file-selector-button')
|
||||
|
||||
// TODO: Use `addVariant('before', '*::before')` instead, once `content`
|
||||
// fix is implemented.
|
||||
addVariant('before', ({ format, withRule }) => {
|
||||
format('&::before')
|
||||
|
||||
withRule((rule) => {
|
||||
addVariant('before', ({ container }) => {
|
||||
container.walkRules((rule) => {
|
||||
let foundContent = false
|
||||
rule.walkDecls('content', () => {
|
||||
foundContent = true
|
||||
})
|
||||
|
||||
if (!foundContent) {
|
||||
rule.prepend(postcss.decl({ prop: 'content', value: '""' }))
|
||||
rule.prepend(postcss.decl({ prop: 'content', value: 'var(--tw-content)' }))
|
||||
}
|
||||
})
|
||||
|
||||
return '&::before'
|
||||
})
|
||||
|
||||
// TODO: Use `addVariant('after', '*::after')` instead, once `content`
|
||||
// fix is implemented.
|
||||
addVariant('after', ({ format, withRule }) => {
|
||||
format('&::after')
|
||||
|
||||
withRule((rule) => {
|
||||
addVariant('after', ({ container }) => {
|
||||
container.walkRules((rule) => {
|
||||
let foundContent = false
|
||||
rule.walkDecls('content', () => {
|
||||
foundContent = true
|
||||
})
|
||||
|
||||
if (!foundContent) {
|
||||
rule.prepend(postcss.decl({ prop: 'content', value: '""' }))
|
||||
rule.prepend(postcss.decl({ prop: 'content', value: 'var(--tw-content)' }))
|
||||
}
|
||||
})
|
||||
|
||||
return '&::after'
|
||||
})
|
||||
},
|
||||
|
||||
|
|
@ -112,22 +109,22 @@ export let variantPlugins = {
|
|||
},
|
||||
|
||||
directionVariants: ({ addVariant }) => {
|
||||
addVariant('ltr', ({ format }) => {
|
||||
addVariant('ltr', () => {
|
||||
log.warn('rtl-experimental', [
|
||||
'The RTL features in Tailwind CSS are currently in preview.',
|
||||
'Preview features are not covered by semver, and may be improved in breaking ways at any time.',
|
||||
])
|
||||
|
||||
format('[dir="ltr"] &')
|
||||
return '[dir="ltr"] &'
|
||||
})
|
||||
|
||||
addVariant('rtl', ({ format }) => {
|
||||
addVariant('rtl', () => {
|
||||
log.warn('rtl-experimental', [
|
||||
'The RTL features in Tailwind CSS are currently in preview.',
|
||||
'Preview features are not covered by semver, and may be improved in breaking ways at any time.',
|
||||
])
|
||||
|
||||
format('[dir="rtl"] &')
|
||||
return '[dir="rtl"] &'
|
||||
})
|
||||
},
|
||||
|
||||
|
|
@ -2265,5 +2262,7 @@ export let corePlugins = {
|
|||
{ filterDefault: true }
|
||||
),
|
||||
willChange: createUtilityPlugin('willChange', [['will-change', ['will-change']]]),
|
||||
content: createUtilityPlugin('content'),
|
||||
content: createUtilityPlugin('content', [
|
||||
['content', ['--tw-content', ['content', 'var(--tw-content)']]],
|
||||
]),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,11 @@
|
|||
border-color: currentColor; /* 2 */
|
||||
}
|
||||
|
||||
::before,
|
||||
::after {
|
||||
--tw-content: '';
|
||||
}
|
||||
|
||||
/*
|
||||
1. Use a consistent sensible line-height in all browsers.
|
||||
2. Prevent adjustments of font size after orientation changes in iOS.
|
||||
|
|
|
|||
|
|
@ -143,26 +143,30 @@ function applyVariant(variant, matches, context) {
|
|||
}
|
||||
|
||||
let ruleWithVariant = variantFunction({
|
||||
// Public API
|
||||
get container() {
|
||||
prepareBackup()
|
||||
return clone
|
||||
},
|
||||
separator: context.tailwindConfig.separator,
|
||||
modifySelectors,
|
||||
|
||||
// Private API for now
|
||||
wrap(wrapper) {
|
||||
let nodes = clone.nodes
|
||||
clone.removeAll()
|
||||
wrapper.append(nodes)
|
||||
clone.append(wrapper)
|
||||
},
|
||||
withRule(modify) {
|
||||
clone.walkRules(modify)
|
||||
},
|
||||
format(selectorFormat) {
|
||||
collectedFormats.push(selectorFormat)
|
||||
},
|
||||
})
|
||||
|
||||
if (typeof ruleWithVariant === 'string') {
|
||||
collectedFormats.push(ruleWithVariant)
|
||||
}
|
||||
|
||||
if (ruleWithVariant === null) {
|
||||
continue
|
||||
}
|
||||
|
|
|
|||
|
|
@ -217,7 +217,10 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
|
|||
addVariant(variantName, variantFunctions, options = {}) {
|
||||
variantFunctions = [].concat(variantFunctions).map((variantFunction) => {
|
||||
if (typeof variantFunction !== 'string') {
|
||||
return variantFunction
|
||||
// Safelist public API functions
|
||||
return ({ modifySelectors, container, separator }) => {
|
||||
return variantFunction({ modifySelectors, container, separator })
|
||||
}
|
||||
}
|
||||
|
||||
variantFunction = variantFunction
|
||||
|
|
|
|||
|
|
@ -1011,13 +1011,16 @@
|
|||
will-change: var(--will-change);
|
||||
}
|
||||
.content-\[\'hello\'\] {
|
||||
content: 'hello';
|
||||
--tw-content: 'hello';
|
||||
content: var(--tw-content);
|
||||
}
|
||||
.content-\[attr\(content-before\)\] {
|
||||
content: attr(content-before);
|
||||
--tw-content: attr(content-before);
|
||||
content: var(--tw-content);
|
||||
}
|
||||
.content-\[\'\>\'\] {
|
||||
content: '>';
|
||||
--tw-content: '>';
|
||||
content: var(--tw-content);
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
.lg\:grid-cols-\[200px\2c repeat\(auto-fill\2c minmax\(15\%\2c 100px\)\)\2c 300px\] {
|
||||
|
|
|
|||
|
|
@ -176,15 +176,18 @@ it('should convert _ to spaces', () => {
|
|||
}
|
||||
|
||||
.content-\\[_hello_world_\\] {
|
||||
content: hello world;
|
||||
--tw-content: hello world;
|
||||
content: var(--tw-content);
|
||||
}
|
||||
|
||||
.content-\\[___abc____\\] {
|
||||
content: abc;
|
||||
--tw-content: abc;
|
||||
content: var(--tw-content);
|
||||
}
|
||||
|
||||
.content-\\[\\'__hello__world__\\'\\] {
|
||||
content: ' hello world ';
|
||||
--tw-content: ' hello world ';
|
||||
content: var(--tw-content);
|
||||
}
|
||||
`)
|
||||
})
|
||||
|
|
@ -199,7 +202,8 @@ it('should not convert escaped underscores with spaces', () => {
|
|||
return run('@tailwind utilities', config).then((result) => {
|
||||
return expect(result.css).toMatchFormattedCss(css`
|
||||
.content-\[\'snake\\_case\'\] {
|
||||
content: 'snake_case';
|
||||
--tw-content: 'snake_case';
|
||||
content: var(--tw-content);
|
||||
}
|
||||
`)
|
||||
})
|
||||
|
|
|
|||
|
|
@ -968,5 +968,6 @@
|
|||
will-change: transform;
|
||||
}
|
||||
.content-none {
|
||||
content: none;
|
||||
--tw-content: none;
|
||||
content: var(--tw-content);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,8 @@ test('arbitrary values with quotes', async () => {
|
|||
return run('@tailwind utilities', config).then((result) => {
|
||||
expect(result.css).toMatchFormattedCss(css`
|
||||
.content-\[\'hello\]\'\] {
|
||||
content: 'hello]';
|
||||
--tw-content: 'hello]';
|
||||
content: var(--tw-content);
|
||||
}
|
||||
`)
|
||||
})
|
||||
|
|
|
|||
|
|
@ -121,12 +121,12 @@ test('with pseudo-element variants', async () => {
|
|||
}
|
||||
/* --- */
|
||||
.before\:scale-x-110::before {
|
||||
content: '';
|
||||
content: var(--tw-content);
|
||||
--tw-scale-x: 1.1;
|
||||
transform: var(--tw-transform);
|
||||
}
|
||||
.after\:rotate-3::after {
|
||||
content: '';
|
||||
content: var(--tw-content);
|
||||
--tw-rotate: 3deg;
|
||||
transform: var(--tw-transform);
|
||||
}
|
||||
|
|
@ -205,12 +205,12 @@ test('with multi-class pseudo-element variants', async () => {
|
|||
}
|
||||
/* --- */
|
||||
.group:hover .group-hover\:before\:scale-x-110::before {
|
||||
content: '';
|
||||
content: var(--tw-content);
|
||||
--tw-scale-x: 1.1;
|
||||
transform: var(--tw-transform);
|
||||
}
|
||||
.peer:focus ~ .peer-focus\:after\:rotate-3::after {
|
||||
content: '';
|
||||
content: var(--tw-content);
|
||||
--tw-rotate: 3deg;
|
||||
transform: var(--tw-transform);
|
||||
}
|
||||
|
|
@ -253,12 +253,12 @@ test('with multi-class pseudo-element and pseudo-class variants', async () => {
|
|||
}
|
||||
/* --- */
|
||||
.group:hover .group-hover\:hover\:before\:scale-x-110::before:hover {
|
||||
content: '';
|
||||
content: var(--tw-content);
|
||||
--tw-scale-x: 1.1;
|
||||
transform: var(--tw-transform);
|
||||
}
|
||||
.peer:focus ~ .peer-focus\:focus\:after\:rotate-3::after:focus {
|
||||
content: '';
|
||||
content: var(--tw-content);
|
||||
--tw-rotate: 3deg;
|
||||
transform: var(--tw-transform);
|
||||
}
|
||||
|
|
@ -288,7 +288,6 @@ test('with apply', async () => {
|
|||
}
|
||||
|
||||
.baz::before {
|
||||
content: '';
|
||||
@apply rotate-45;
|
||||
}
|
||||
|
||||
|
|
@ -351,13 +350,12 @@ test('with apply', async () => {
|
|||
transform: var(--tw-transform);
|
||||
}
|
||||
.bar::before {
|
||||
content: '';
|
||||
content: var(--tw-content);
|
||||
--tw-scale-x: 1.1;
|
||||
--tw-scale-y: 1.1;
|
||||
transform: var(--tw-transform);
|
||||
}
|
||||
.baz::before {
|
||||
content: '';
|
||||
--tw-rotate: 45deg;
|
||||
transform: var(--tw-transform);
|
||||
}
|
||||
|
|
@ -408,22 +406,18 @@ test('legacy pseudo-element syntax is supported', async () => {
|
|||
@tailwind utilities;
|
||||
|
||||
.a:before {
|
||||
content: '';
|
||||
@apply rotate-45;
|
||||
}
|
||||
|
||||
.b:after {
|
||||
content: '';
|
||||
@apply rotate-3;
|
||||
}
|
||||
|
||||
.c:first-line {
|
||||
content: '';
|
||||
@apply rotate-1;
|
||||
}
|
||||
|
||||
.d:first-letter {
|
||||
content: '';
|
||||
@apply rotate-6;
|
||||
}
|
||||
`
|
||||
|
|
@ -447,22 +441,18 @@ test('legacy pseudo-element syntax is supported', async () => {
|
|||
}
|
||||
/* --- */
|
||||
.a:before {
|
||||
content: '';
|
||||
--tw-rotate: 45deg;
|
||||
transform: var(--tw-transform);
|
||||
}
|
||||
.b:after {
|
||||
content: '';
|
||||
--tw-rotate: 3deg;
|
||||
transform: var(--tw-transform);
|
||||
}
|
||||
.c:first-line {
|
||||
content: '';
|
||||
--tw-rotate: 1deg;
|
||||
transform: var(--tw-transform);
|
||||
}
|
||||
.d:first-letter {
|
||||
content: '';
|
||||
--tw-rotate: 6deg;
|
||||
transform: var(--tw-transform);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -165,20 +165,20 @@
|
|||
color: rgb(255 255 255 / var(--tw-text-opacity));
|
||||
}
|
||||
.before\:block::before {
|
||||
content: '';
|
||||
content: var(--tw-content);
|
||||
display: block;
|
||||
}
|
||||
.before\:bg-red-500::before {
|
||||
content: '';
|
||||
content: var(--tw-content);
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(239 68 68 / var(--tw-bg-opacity));
|
||||
}
|
||||
.after\:flex::after {
|
||||
content: '';
|
||||
content: var(--tw-content);
|
||||
display: flex;
|
||||
}
|
||||
.after\:uppercase::after {
|
||||
content: '';
|
||||
content: var(--tw-content);
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.first\:shadow-md:first-child {
|
||||
|
|
|
|||
|
|
@ -61,9 +61,7 @@ describe('custom advanced variants', () => {
|
|||
],
|
||||
plugins: [
|
||||
function ({ addVariant }) {
|
||||
addVariant('prose-headings', ({ format }) => {
|
||||
return format(':where(&) :is(h1, h2, h3, h4)')
|
||||
})
|
||||
addVariant('prose-headings', ':where(&) :is(h1, h2, h3, h4)')
|
||||
},
|
||||
],
|
||||
}
|
||||
|
|
@ -89,9 +87,7 @@ describe('custom advanced variants', () => {
|
|||
],
|
||||
plugins: [
|
||||
function ({ addVariant }) {
|
||||
addVariant('prose-headings', ({ format }) => {
|
||||
return format(':where(&) :is(h1, h2, h3, h4)')
|
||||
})
|
||||
addVariant('prose-headings', ':where(&) :is(h1, h2, h3, h4)')
|
||||
},
|
||||
],
|
||||
}
|
||||
|
|
@ -121,9 +117,7 @@ describe('custom advanced variants', () => {
|
|||
],
|
||||
plugins: [
|
||||
function ({ addVariant }) {
|
||||
addVariant('prose-headings', ({ format }) => {
|
||||
return format(':where(&) :is(h1, h2, h3, h4)')
|
||||
})
|
||||
addVariant('prose-headings', ':where(&) :is(h1, h2, h3, h4)')
|
||||
},
|
||||
],
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue