Skip to content

Commit

Permalink
Insert @defaults at start of stylesheet (#14427)
Browse files Browse the repository at this point in the history
Prior to this PR, we'd put all of the `@defaults` (the CSS variables and
stuff) _after_ the `base` rules. This creates an issue when using
`optimizeUniversalDefaults` with CSS that looks like this:

```css
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
  input {
    @apply shadow;
  }
}
```

…because the default shadow stuff ends up after the base `input` rules,
so the generated styles are like this:

```css
input {
  --tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
  --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color),
    0 1px 2px -1px var(--tw-shadow-color);
  box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
    var(--tw-shadow);
}

input {
  --tw-ring-offset-shadow: 0 0 #0000;
  --tw-ring-shadow: 0 0 #0000;
  --tw-shadow: 0 0 #0000;
  --tw-shadow-colored: 0 0 #0000;
}
```

This means all of the actual shadow values for the input are reset and
the shadow doesn't work.

Fixes #14426.

Lots of failing tests right because this changes a ton of stuff, albeit
in a totally inconsequential way. @thecrypticace if you could update
these for me this week that would be a huge help, just banging this fix
out quick while the kids are napping 😴

---------

Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
Co-authored-by: Jordan Pittman <jordan@cryptica.me>
  • Loading branch information
3 people committed Sep 17, 2024
1 parent 818d10a commit fe48ca8
Show file tree
Hide file tree
Showing 13 changed files with 376 additions and 339 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

- Nothing yet!
### Fixed

- Ensure using `@apply` with utilities that use `@defaults` works with rules defined in the base layer when using `optimizeUniversalDefaults` ([#14427](https://github.com/tailwindlabs/tailwindcss/pull/14427))

## [3.4.11] - 2024-09-11

Expand Down
2 changes: 1 addition & 1 deletion src/lib/expandTailwindAtRules.js
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ export default function expandTailwindAtRules(context) {

if (layerNodes.base) {
layerNodes.base.before(
cloneNodes([...baseNodes, ...defaultNodes], layerNodes.base.source, {
cloneNodes([...defaultNodes, ...baseNodes], layerNodes.base.source, {
layer: 'base',
})
)
Expand Down
24 changes: 11 additions & 13 deletions src/lib/resolveDefaultsAtRules.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,22 +118,20 @@ export default function resolveDefaultsAtRules({ tailwindConfig }) {
}
}

if (flagEnabled(tailwindConfig, 'optimizeUniversalDefaults')) {
if (selectorGroups.size === 0) {
universal.remove()
continue
}
if (selectorGroups.size === 0) {
universal.remove()
continue
}

for (let [, selectors] of selectorGroups) {
let universalRule = postcss.rule({
source: universal.source,
})
for (let [, selectors] of selectorGroups) {
let universalRule = postcss.rule({
source: universal.source,
})

universalRule.selectors = [...selectors]
universalRule.selectors = [...selectors]

universalRule.append(universal.nodes.map((node) => node.clone()))
universal.before(universalRule)
}
universalRule.append(universal.nodes.map((node) => node.clone()))
universal.before(universalRule)
}

universal.remove()
Expand Down
2 changes: 1 addition & 1 deletion tests/apply.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1640,6 +1640,7 @@ it('apply partitioning works with media queries', async () => {
const result = await run(input, config)

expect(result.css).toMatchFormattedCss(css`
${defaults}
html,
body {
--tw-text-opacity: 1;
Expand All @@ -1654,7 +1655,6 @@ it('apply partitioning works with media queries', async () => {
font-size: 2rem;
}
}
${defaults}
`)
})

Expand Down
2 changes: 1 addition & 1 deletion tests/basic-usage.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -460,11 +460,11 @@ it('does not produce duplicate output when seeing variants preceding a wildcard
* {
color: #00f;
}
${defaults}
.combined,
* {
color: red;
}
${defaults}
.underline {
text-decoration-line: underline;
}
Expand Down
2 changes: 1 addition & 1 deletion tests/collapse-adjacent-rules.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ test('collapse adjacent rules', () => {

return run(input, config).then((result) => {
expect(result.css).toMatchFormattedCss(css`
${defaults}
@font-face {
font-family: Poppins;
src: url('/fonts/Poppins.woff2') format('woff2'), url('/fonts/Poppins.woff') format('woff');
Expand All @@ -79,7 +80,6 @@ test('collapse adjacent rules', () => {
src: url('/fonts/ProximaNova.woff2') format('woff2'),
url('/fonts/ProximaNova.woff') format('woff');
}
${defaults}
@font-face {
font-family: Inter;
src: url('/fonts/Inter.woff2') format('woff2'), url('/fonts/Inter.woff') format('woff');
Expand Down
2 changes: 1 addition & 1 deletion tests/combined-selectors.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@ it('should generate the partial selector, if only a partial is used (base layer)

return run(input, config).then((result) => {
return expect(result.css).toMatchFormattedCss(css`
${defaults}
:root {
font-weight: bold;
}
:root,
.a {
color: #000;
}
${defaults}
`)
})
})
Expand Down
4 changes: 2 additions & 2 deletions tests/custom-plugins.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -239,13 +239,13 @@ test('plugins can add base styles with object syntax', () => {

return run('@tailwind base', config).then((result) => {
expect(result.css).toMatchFormattedCss(css`
${defaults}
img {
max-width: 100%;
}
button {
font-family: inherit;
}
${defaults}
`)
})
})
Expand Down Expand Up @@ -280,13 +280,13 @@ test('plugins can add base styles with raw PostCSS nodes', () => {

return run('@tailwind base', config).then((result) => {
expect(result.css).toMatchFormattedCss(css`
${defaults}
img {
max-width: 100%;
}
button {
font-family: inherit;
}
${defaults}
`)
})
})
Expand Down
2 changes: 1 addition & 1 deletion tests/import-syntax.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ test('using @import instead of @tailwind', () => {

return run(input, config).then((result) => {
expect(result.css).toMatchFormattedCss(css`
${defaults}
h1 {
font-size: 32px;
}
${defaults}
.container {
width: 100%;
}
Expand Down
2 changes: 1 addition & 1 deletion tests/kitchen-sink.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,7 @@ test('it works', () => {
}
}
}
${defaults}
h1 {
font-size: 1.5rem;
font-weight: 700;
Expand All @@ -362,7 +363,6 @@ test('it works', () => {
div {
background: #654321;
}
${defaults}
.container {
width: 100%;
}
Expand Down
8 changes: 4 additions & 4 deletions tests/layer-at-rules.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,12 +90,12 @@ test('comments can be used inside layers without crashing', () => {

return run(input, config).then((result) => {
expect(result.css).toMatchFormattedCss(css`
${defaults}
div {
background-color: #bada55;
}
${defaults}
.important-component,
.important-utility {
.important-utility {
text-align: banana;
}
`)
Expand Down Expand Up @@ -144,10 +144,10 @@ test('comments can be used inside layers (with important) without crashing', ()

return run(input, config).then((result) => {
expect(result.css).toMatchFormattedCss(css`
${defaults}
div {
background-color: #bada55;
}
${defaults}
.important-component {
text-align: banana;
}
Expand Down Expand Up @@ -245,6 +245,7 @@ test('layers are grouped and inserted at the matching @tailwind rule', () => {
font-weight: medium;
}
}
${defaults}
body {
margin: 0;
}
Expand All @@ -254,7 +255,6 @@ test('layers are grouped and inserted at the matching @tailwind rule', () => {
p {
font-weight: normal;
}
${defaults}
.input {
background: #fff;
}
Expand Down
38 changes: 38 additions & 0 deletions tests/resolve-defaults-at-rules.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -770,6 +770,44 @@ test('no defaults and apply without @tailwind base', () => {
})
})

test('apply to rule in base layer puts defaults first with optimizeUniversalDefaults', () => {
let config = {
experimental: { optimizeUniversalDefaults: true },
content: [{ raw: html`<div class="my-card"></div>` }],
corePlugins: ['boxShadow'],
}

// Optimize universal defaults doesn't work well with isolated modules
// We require you to use @tailwind base to inject the defaults
let input = css`
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
input {
@apply shadow;
}
}
`

return run(input, config).then((result) => {
return expect(result.css).toMatchFormattedCss(css`
input {
--tw-ring-offset-shadow: 0 0 #0000;
--tw-ring-shadow: 0 0 #0000;
--tw-shadow: 0 0 #0000;
--tw-shadow-colored: 0 0 #0000;
--tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color),
0 1px 2px -1px var(--tw-shadow-color);
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
var(--tw-shadow);
}
`)
})
})

test('optimize universal defaults groups :has separately', () => {
let config = {
experimental: { optimizeUniversalDefaults: true },
Expand Down
Loading

0 comments on commit fe48ca8

Please sign in to comment.