From eec1bf2b84ab0824b7d2e6ee0bed7413b72b813f Mon Sep 17 00:00:00 2001 From: Philipp Spiess Date: Mon, 31 Mar 2025 13:06:28 +0200 Subject: [PATCH] =?UTF-8?q?Fix=20`--theme(=E2=80=A6)`=20function=20when=20?= =?UTF-8?q?legacy=20JS=20plugins=20are=20used=20(#17458)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #17346 This PR fixes an issue that caused the `--theme(…)` function to behave differently after a legacy JS plugin or config was configured. The issue was that the compatibility layer would patch the theme value resolver to always inline the value. This, however, is only expected to happen if the path does not look like a CSS variable in which case this legacy code path should not be run. To fix this, I'm now keeping a reference to the regular theme resolution function and call into it if the path starts with `--`. ## Test plan - Tested with the repro in #17346 by adding pnpm overrides and confirmed that this fixes the issue - Added a unit test to the `--theme(…)` resolution tests --- CHANGELOG.md | 1 + .../src/compat/apply-compat-hooks.ts | 7 +++- .../tailwindcss/src/css-functions.test.ts | 42 +++++++++++++++++++ 3 files changed, 49 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4478ae7f3..13f205219 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Extract special `@("@")md:…` syntax in Razor files ([#17427](https://github.com/tailwindlabs/tailwindcss/pull/17427)) - Disallow arbitrary values with top-level braces and semicolons as well as unbalanced parentheses and brackets ([#17361](https://github.com/tailwindlabs/tailwindcss/pull/17361)) - Extract used CSS variables from `.css` files ([#17433](https://github.com/tailwindlabs/tailwindcss/pull/17433)) +- Ensure the `--theme(…)` function still resolves to the CSS variables even when legacy JS plugins are enabled ### Changed diff --git a/packages/tailwindcss/src/compat/apply-compat-hooks.ts b/packages/tailwindcss/src/compat/apply-compat-hooks.ts index 1cf9b1ce5..a781cdcb0 100644 --- a/packages/tailwindcss/src/compat/apply-compat-hooks.ts +++ b/packages/tailwindcss/src/compat/apply-compat-hooks.ts @@ -260,8 +260,13 @@ function upgradeToFullPluginSupport({ // config files are actually being used. In the future we may want to optimize // this further by only doing this if plugins or config files _actually_ // registered JS config objects. + let defaultResolveThemeValue = designSystem.resolveThemeValue designSystem.resolveThemeValue = function resolveThemeValue(path: string, forceInline?: boolean) { - let resolvedValue = pluginApi.theme(path, forceInline) + if (path[0] === '-' && path[1] === '-') { + return defaultResolveThemeValue(path, forceInline) + } + + let resolvedValue = pluginApi.theme(path, undefined) if (Array.isArray(resolvedValue) && resolvedValue.length === 2) { // When a tuple is returned, return the first element diff --git a/packages/tailwindcss/src/css-functions.test.ts b/packages/tailwindcss/src/css-functions.test.ts index 29e09d7d8..e8b1611aa 100644 --- a/packages/tailwindcss/src/css-functions.test.ts +++ b/packages/tailwindcss/src/css-functions.test.ts @@ -384,6 +384,48 @@ describe('--theme(…)', () => { `[Error: Could not resolve value for theme function: \`theme(--color-green-500)\`. Consider checking if the variable name is correct or provide a fallback value to silence this error.]`, ) }) + + test('--theme(…) function still works as expected, even when a plugin is imported', async () => { + expect( + await compileCss( + css` + @layer base { + html, + :host { + font-family: --theme(--default-font-family, system-ui); + } + } + @layer theme { + @theme { + --font-sans: sans-serif; + --default-font-family: --theme(--font-sans, initial); + } + } + @plugin "my-plugin.js"; + `, + [], + { + loadModule: async () => ({ + module: () => {}, + base: '/root', + }), + }, + ), + ).toMatchInlineSnapshot(` + "@layer base { + html, :host { + font-family: var(--default-font-family, system-ui); + } + } + + @layer theme { + :root, :host { + --font-sans: sans-serif; + --default-font-family: var(--font-sans); + } + }" + `) + }) }) describe('theme(…)', () => {