Move important selector to the front when @apply-ing selector-modifying variants in custom utilities (#8313)

* Fix generated utilities using `@apply` with important selectors

* Update changelog
This commit is contained in:
Jordan Pittman 2022-05-09 14:20:36 -04:00 • committed by GitHub
parent be51739337
commit b49dc7cafa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 103 additions and 1 deletions

View file

@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Remove default `[hidden]` style in preflight ([#8248](https://github.com/tailwindlabs/tailwindcss/pull/8248))
- Only check selectors containing base apply candidates for circular dependencies ([#8222](https://github.com/tailwindlabs/tailwindcss/pull/8222))
- Rewrite default class extractor ([#8204](https://github.com/tailwindlabs/tailwindcss/pull/8204))
- Move `important` selector to the front when `@apply`-ing selector-modifying variants in custom utilities ([#8313](https://github.com/tailwindlabs/tailwindcss/pull/8313))
### Changed

View file

@ -471,7 +471,27 @@ function processApply(root, context, localCache) {
return
}
rule.selector = replaceSelector(parent.selector, rule.selector, applyCandidate)
// Strip the important selector from the parent selector if at the beginning
let importantSelector =
typeof context.tailwindConfig.important === 'string'
? context.tailwindConfig.important
: null
// We only want to move the "important" selector if this is a Tailwind-generated utility
// We do *not* want to do this for user CSS that happens to be structured the same
let isGenerated = parent.raws.tailwind !== undefined
let parentSelector =
isGenerated && importantSelector && parent.selector.indexOf(importantSelector) === 0
? parent.selector.slice(importantSelector.length)
: parent.selector
rule.selector = replaceSelector(parentSelector, rule.selector, applyCandidate)
// And then re-add it if it was removed
if (importantSelector && parentSelector !== parent.selector) {
rule.selector = `${importantSelector} ${rule.selector}`
}
rule.walkDecls((d) => {
d.important = meta.important || important

View file

@ -1467,3 +1467,84 @@ it('should apply using the updated user CSS when the source has changed', async
}
`)
})
it('apply + layer utilities + selector variants (like group) + important selector', async () => {
let config = {
important: '#myselector',
content: [{ raw: html`<div class="custom-utility"></div>` }],
plugins: [],
}
let input = css`
@tailwind utilities;
@layer utilities {
.custom-utility {
@apply font-normal group-hover:underline;
}
}
`
let result = await run(input, config)
expect(result.css).toMatchFormattedCss(css`
#myselector .custom-utility {
font-weight: 400;
}
#myselector .group:hover .custom-utility {
text-decoration-line: underline;
}
`)
})
it('apply + user CSS + selector variants (like group) + important selector (1)', async () => {
let config = {
important: '#myselector',
content: [{ raw: html`<div class="custom-utility"></div>` }],
plugins: [],
}
let input = css`
.custom-utility {
@apply font-normal group-hover:underline;
}
`
let result = await run(input, config)
expect(result.css).toMatchFormattedCss(css`
.custom-utility {
font-weight: 400;
}
.group:hover .custom-utility {
text-decoration-line: underline;
}
`)
})
it('apply + user CSS + selector variants (like group) + important selector (2)', async () => {
let config = {
important: '#myselector',
content: [{ raw: html`<div class="custom-utility"></div>` }],
plugins: [],
}
let input = css`
#myselector .custom-utility {
@apply font-normal group-hover:underline;
}
`
let result = await run(input, config)
expect(result.css).toMatchFormattedCss(css`
#myselector .custom-utility {
font-weight: 400;
}
.group:hover #myselector .custom-utility {
text-decoration-line: underline;
}
`)
})