Skip to content

Commit 4e200f4

Browse files
Make reference mode emit var fallbacks instead of all CSS vars
1 parent 13fac81 commit 4e200f4

File tree

9 files changed

+89
-142
lines changed

9 files changed

+89
-142
lines changed

packages/@tailwindcss-postcss/src/index.test.ts

+2-6
Original file line numberDiff line numberDiff line change
@@ -99,12 +99,8 @@ test('@apply can be used without emitting the theme in the CSS file', async () =
9999
)
100100

101101
expect(result.css.trim()).toMatchInlineSnapshot(`
102-
":root, :host {
103-
--color-red-500: oklch(.637 .237 25.331);
104-
}
105-
106-
.foo {
107-
color: var(--color-red-500);
102+
".foo {
103+
color: var(--color-red-500, oklch(.637 .237 25.331));
108104
}"
109105
`)
110106
})

packages/tailwindcss/src/ast.ts

+2-25
Original file line numberDiff line numberDiff line change
@@ -256,11 +256,7 @@ export function walkDepth(
256256

257257
// Optimize the AST for printing where all the special nodes that require custom
258258
// handling are handled such that the printing is a 1-to-1 transformation.
259-
export function optimizeAst(
260-
ast: AstNode[],
261-
designSystem: DesignSystem,
262-
firstThemeRule: StyleRule | null,
263-
) {
259+
export function optimizeAst(ast: AstNode[], designSystem: DesignSystem) {
264260
let atRoots: AstNode[] = []
265261
let seenAtProperties = new Set<string>()
266262
let cssThemeVariables = new DefaultMap<
@@ -396,27 +392,8 @@ export function optimizeAst(
396392

397393
// Context
398394
else if (node.kind === 'context') {
395+
// Remove reference imports from printing
399396
if (node.context.reference) {
400-
if (firstThemeRule) {
401-
let path = findNode(node.nodes, (node) => node === firstThemeRule)
402-
if (path) {
403-
let newPathToFirstThemeRule = path
404-
.filter((node) => node.kind === 'at-rule')
405-
.map((node) => ({ ...node, nodes: [] }))
406-
.reverse() as AtRule[]
407-
408-
let child = firstThemeRule as AstNode
409-
for (let node of newPathToFirstThemeRule) {
410-
node.nodes = [child]
411-
child = node
412-
}
413-
414-
let newParent: AstNode[] = []
415-
transform(child, newParent, { ...context, ...node.context, reference: false }, depth)
416-
parent.push(...newParent)
417-
}
418-
}
419-
420397
return
421398
} else {
422399
for (let child of node.nodes) {

packages/tailwindcss/src/at-import.test.ts

+3-7
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,7 @@ test('supports theme(reference) imports', async () => {
421421
),
422422
).resolves.toMatchInlineSnapshot(`
423423
".text-red-500 {
424-
color: var(--color-red-500);
424+
color: var(--color-red-500, red);
425425
}
426426
"
427427
`)
@@ -580,12 +580,8 @@ test('resolves @reference as `@import "…" reference`', async () => {
580580
{ loadStylesheet, candidates: ['text-red-500'] },
581581
),
582582
).resolves.toMatchInlineSnapshot(`
583-
":root, :host {
584-
--color-red-500: red;
585-
}
586-
587-
.text-red-500 {
588-
color: var(--color-red-500);
583+
".text-red-500 {
584+
color: var(--color-red-500, red);
589585
}
590586
"
591587
`)

packages/tailwindcss/src/compat/config.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1389,7 +1389,7 @@ test('blocklisted candidates are not generated', async () => {
13891389
}
13901390
.md\\:bg-white {
13911391
@media (width >= 48rem) {
1392-
background-color: var(--color-white);
1392+
background-color: var(--color-white, #fff);
13931393
}
13941394
}
13951395
"

packages/tailwindcss/src/index.test.ts

+12-43
Original file line numberDiff line numberDiff line change
@@ -1842,7 +1842,7 @@ describe('Parsing theme values from CSS', () => {
18421842
}
18431843
18441844
.bg-potato {
1845-
background-color: var(--color-potato);
1845+
background-color: var(--color-potato, #ac855b);
18461846
}
18471847
18481848
.bg-tomato {
@@ -1874,7 +1874,7 @@ describe('Parsing theme values from CSS', () => {
18741874
),
18751875
).toMatchInlineSnapshot(`
18761876
".animate-foo {
1877-
animation: var(--animate-foo);
1877+
animation: var(--animate-foo, foo 1s infinite);
18781878
}"
18791879
`)
18801880
})
@@ -1911,7 +1911,7 @@ describe('Parsing theme values from CSS', () => {
19111911
}
19121912
19131913
.animate-foo {
1914-
animation: var(--animate-foo);
1914+
animation: var(--animate-foo, foo 1s infinite);
19151915
}
19161916
19171917
.bg-pink {
@@ -1936,7 +1936,7 @@ describe('Parsing theme values from CSS', () => {
19361936
),
19371937
).toMatchInlineSnapshot(`
19381938
".bg-potato {
1939-
background-color: var(--color-potato);
1939+
background-color: var(--color-potato, #c794aa);
19401940
}"
19411941
`)
19421942
})
@@ -1991,11 +1991,11 @@ describe('Parsing theme values from CSS', () => {
19911991
}
19921992
19931993
.bg-avocado {
1994-
background-color: var(--color-avocado);
1994+
background-color: var(--color-avocado, #c0cc6d);
19951995
}
19961996
19971997
.bg-potato {
1998-
background-color: var(--color-potato);
1998+
background-color: var(--color-potato, #ac855b);
19991999
}
20002000
20012001
.bg-tomato {
@@ -2323,7 +2323,7 @@ describe('Parsing theme values from CSS', () => {
23232323
),
23242324
).toMatchInlineSnapshot(`
23252325
".bg-potato {
2326-
background-color: var(--color-potato);
2326+
background-color: var(--color-potato, #efb46b);
23272327
}"
23282328
`)
23292329
})
@@ -3849,20 +3849,8 @@ describe('`@reference "…" reference`', () => {
38493849
},
38503850
),
38513851
).resolves.toMatchInlineSnapshot(`
3852-
"@layer theme {
3853-
:root, :host {
3854-
--animate-spin: spin 1s linear infinite;
3855-
}
3856-
}
3857-
3858-
.bar {
3859-
animation: var(--animate-spin);
3860-
}
3861-
3862-
@keyframes spin {
3863-
to {
3864-
transform: rotate(360deg);
3865-
}
3852+
".bar {
3853+
animation: var(--animate-spin, spin 1s linear infinite);
38663854
}"
38673855
`)
38683856
})
@@ -3924,28 +3912,9 @@ describe('`@reference "…" reference`', () => {
39243912
{ loadStylesheet },
39253913
),
39263914
).resolves.toMatchInlineSnapshot(`
3927-
"@layer two {
3928-
@layer three {
3929-
:root, :host {
3930-
--color-red: red;
3931-
--animate-wiggle: wiggle 1s ease-in-out infinite;
3932-
}
3933-
}
3934-
}
3935-
3936-
.bar {
3937-
animation: var(--animate-wiggle);
3938-
color: var(--color-red);
3939-
}
3940-
3941-
@keyframes wiggle {
3942-
0%, 100% {
3943-
transform: rotate(-3deg);
3944-
}
3945-
3946-
50% {
3947-
transform: rotate(3deg);
3948-
}
3915+
".bar {
3916+
animation: var(--animate-wiggle, wiggle 1s ease-in-out infinite);
3917+
color: var(--color-red, red);
39493918
}"
39503919
`)
39513920
})

packages/tailwindcss/src/index.ts

+9-9
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,10 @@ async function parseCss(
448448
if (node.name === '@theme') {
449449
let [themeOptions, themePrefix] = parseThemeOptions(node.params)
450450

451+
if (context.reference) {
452+
themeOptions |= ThemeOptions.REFERENCE
453+
}
454+
451455
if (themePrefix) {
452456
if (!IS_VALID_PREFIX.test(themePrefix)) {
453457
throw new Error(
@@ -603,7 +607,6 @@ async function parseCss(
603607
root,
604608
utilitiesNode,
605609
features,
606-
firstThemeRule,
607610
}
608611
}
609612

@@ -616,10 +619,7 @@ export async function compileAst(
616619
features: Features
617620
build(candidates: string[]): AstNode[]
618621
}> {
619-
let { designSystem, ast, globs, root, utilitiesNode, features, firstThemeRule } = await parseCss(
620-
input,
621-
opts,
622-
)
622+
let { designSystem, ast, globs, root, utilitiesNode, features } = await parseCss(input, opts)
623623

624624
if (process.env.NODE_ENV !== 'test') {
625625
ast.unshift(comment(`! tailwindcss v${version} | MIT License | https://tailwindcss.com `))
@@ -647,7 +647,7 @@ export async function compileAst(
647647
}
648648

649649
if (!utilitiesNode) {
650-
compiled ??= optimizeAst(ast, designSystem, firstThemeRule)
650+
compiled ??= optimizeAst(ast, designSystem)
651651
return compiled
652652
}
653653

@@ -669,7 +669,7 @@ export async function compileAst(
669669
// If no new candidates were added, we can return the original CSS. This
670670
// currently assumes that we only add new candidates and never remove any.
671671
if (!didChange) {
672-
compiled ??= optimizeAst(ast, designSystem, firstThemeRule)
672+
compiled ??= optimizeAst(ast, designSystem)
673673
return compiled
674674
}
675675

@@ -681,15 +681,15 @@ export async function compileAst(
681681
// CSS. This currently assumes that we only add new ast nodes and never
682682
// remove any.
683683
if (previousAstNodeCount === newNodes.length) {
684-
compiled ??= optimizeAst(ast, designSystem, firstThemeRule)
684+
compiled ??= optimizeAst(ast, designSystem)
685685
return compiled
686686
}
687687

688688
previousAstNodeCount = newNodes.length
689689

690690
utilitiesNode.nodes = newNodes
691691

692-
compiled = optimizeAst(ast, designSystem, firstThemeRule)
692+
compiled = optimizeAst(ast, designSystem)
693693
return compiled
694694
},
695695
}

packages/tailwindcss/src/prefix.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ test('a prefix can be configured via @import theme(…)', async () => {
228228
]),
229229
).toMatchInlineSnapshot(`
230230
".tw\\:bg-potato {
231-
background-color: var(--tw-color-potato);
231+
background-color: var(--tw-color-potato, #7a4724);
232232
}
233233
.tw\\:custom {
234234
color: red;

packages/tailwindcss/src/theme.ts

+11-2
Original file line numberDiff line numberDiff line change
@@ -177,11 +177,20 @@ export class Theme {
177177
}
178178

179179
#var(themeKey: string) {
180-
if (!this.values.has(themeKey)) {
180+
let value = this.values.get(themeKey)
181+
if (!value) {
181182
return null
182183
}
183184

184-
return `var(${escape(this.#prefixKey(themeKey))})`
185+
// Since @theme blocks in reference mode do not emit the CSS variables, we can not assume that
186+
// the values will eventually be set up in the browser (e.g. when using `@apply` inside roots
187+
// that use `@reference`). Ensure we set up a fallback in these cases.
188+
let fallback = null
189+
if (value.options & ThemeOptions.REFERENCE) {
190+
fallback = value.value
191+
}
192+
193+
return `var(${escape(this.#prefixKey(themeKey))}${fallback ? `, ${fallback}` : ''})`
185194
}
186195

187196
markUsedVariable(themeKey: string) {

0 commit comments

Comments
 (0)