From 45417ce2cdf66375114dd0ce9e0dc4ebc33758e1 Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Thu, 29 May 2025 12:37:53 +0200 Subject: [PATCH 1/5] migrate arbitrary modifiers with 0-1 values to bare values --- .../template/migrate-optimize-modifier.test.ts | 3 +++ .../template/migrate-optimize-modifier.ts | 17 +++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/packages/@tailwindcss-upgrade/src/codemods/template/migrate-optimize-modifier.test.ts b/packages/@tailwindcss-upgrade/src/codemods/template/migrate-optimize-modifier.test.ts index d4a6e1bd4afc..3b1459af8702 100644 --- a/packages/@tailwindcss-upgrade/src/codemods/template/migrate-optimize-modifier.test.ts +++ b/packages/@tailwindcss-upgrade/src/codemods/template/migrate-optimize-modifier.test.ts @@ -37,6 +37,9 @@ describe.each([['default'], ['with-variant'], ['important'], ['prefix']])('%s', // Use a bare value modifier ['bg-red-500/[25%]', 'bg-red-500/25'], + // Convert 0-1 values to bare values + ['bg-[#f00]/[0.16]', 'bg-[#f00]/16'], + // Drop unnecessary modifiers ['bg-red-500/[100%]', 'bg-red-500'], ['bg-red-500/100', 'bg-red-500'], diff --git a/packages/@tailwindcss-upgrade/src/codemods/template/migrate-optimize-modifier.ts b/packages/@tailwindcss-upgrade/src/codemods/template/migrate-optimize-modifier.ts index b4d5d58e5681..f07b6680c4a9 100644 --- a/packages/@tailwindcss-upgrade/src/codemods/template/migrate-optimize-modifier.ts +++ b/packages/@tailwindcss-upgrade/src/codemods/template/migrate-optimize-modifier.ts @@ -55,6 +55,23 @@ export function migrateOptimizeModifier( } } + // 3. Try to remove the square brackets, but multiply by 100. E.g.: `[0.16]` -> `16` + if (!changed) { + let newModifier: NamedUtilityValue = { + kind: 'named', + value: `${parseFloat(modifier.value) * 100}`, + fraction: null, + } + + if ( + targetSignature === + signatures.get(designSystem.printCandidate({ ...candidate, modifier: newModifier })) + ) { + changed = true + candidate.modifier = newModifier + } + } + return changed ? designSystem.printCandidate(candidate) : rawCandidate } } From 9e93c6f9cea836773216cf8d96ca8ccedbdc30d4 Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Fri, 30 May 2025 09:35:33 +0200 Subject: [PATCH 2/5] CSS functions in fallback values are allowed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before this, the moment we saw a `(` we stopped trying to convert `bg-[--foo()]` to `bg-(--foo())`. This is because it doesn't make sense to wrap a CSS function in another `var(…)`. However, if that `(` exists in the fallback value, then it's fine and we can still perform the conversion: - `bg-[--my-color,theme(colors.red.500)]` → `bg-(--my-color,theme(colors.red.500))` --- .../migrate-automatic-var-injection.test.ts | 5 +++++ .../migrate-automatic-var-injection.ts | 21 ++++++++++++++++--- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/packages/@tailwindcss-upgrade/src/codemods/template/migrate-automatic-var-injection.test.ts b/packages/@tailwindcss-upgrade/src/codemods/template/migrate-automatic-var-injection.test.ts index d26c185cc3bf..5da651d51b8c 100644 --- a/packages/@tailwindcss-upgrade/src/codemods/template/migrate-automatic-var-injection.test.ts +++ b/packages/@tailwindcss-upgrade/src/codemods/template/migrate-automatic-var-injection.test.ts @@ -40,6 +40,11 @@ test.each([ ['w-[--spacing(5)]', 'w-[--spacing(5)]'], ['bg-[--theme(--color-red-500)]', 'bg-[--theme(--color-red-500)]'], + // Fallback values should be included inside the `var(…)` function + ['bg-[--my-color,red]', 'bg-(--my-color,red)'], + // Fallback values can contain CSS functions + ['bg-[--my-color,theme(spacing.1)]', 'bg-(--my-color,theme(spacing.1))'], + // Some properties never had var() injection in v3. ['[scroll-timeline-name:--myTimeline]', '[scroll-timeline-name:--myTimeline]'], ['[timeline-scope:--myScope]', '[timeline-scope:--myScope]'], diff --git a/packages/@tailwindcss-upgrade/src/codemods/template/migrate-automatic-var-injection.ts b/packages/@tailwindcss-upgrade/src/codemods/template/migrate-automatic-var-injection.ts index 62da826d9336..586d8091daf8 100644 --- a/packages/@tailwindcss-upgrade/src/codemods/template/migrate-automatic-var-injection.ts +++ b/packages/@tailwindcss-upgrade/src/codemods/template/migrate-automatic-var-injection.ts @@ -2,6 +2,7 @@ import { walk, WalkAction } from '../../../../tailwindcss/src/ast' import { type Candidate, type Variant } from '../../../../tailwindcss/src/candidate' import type { Config } from '../../../../tailwindcss/src/compat/plugin-api' import type { DesignSystem } from '../../../../tailwindcss/src/design-system' +import * as ValueParser from '../../../../tailwindcss/src/value-parser' export function migrateAutomaticVarInjection( designSystem: DesignSystem, @@ -73,9 +74,23 @@ export function migrateAutomaticVarInjection( function injectVar(value: string): { value: string; didChange: boolean } { let didChange = false - if (value.startsWith('--') && !value.includes('(')) { - value = `var(${value})` - didChange = true + if (value.startsWith('--')) { + // E.g.: + // + // - `--my-color` → `var(--my-color)` Convert variable + // - `--my-color,red` → `var(--my-color,red)` Convert variable with fallback + // - `--theme(color.red)` → `--theme(color.red)` Do not convert functions + // + if ( + // No `(` definitely means there is no function + !value.includes('(') || + // There could be a function call in the fallback value, but it cannot be + // top-level, so we can safely check the first part + ValueParser.parse(value)[0]?.kind !== 'function' + ) { + value = `var(${value})` + didChange = true + } } else if (value.startsWith(' --')) { value = value.slice(1) didChange = true From 7da70e68d6b55ad62b9555c2f115ffb649322f9d Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Fri, 30 May 2025 12:40:32 +0200 Subject: [PATCH 3/5] add test to ensure fallback values are replaced + fix issue when you are using a CSS variable. In that case you do need the `--tw-` prefix for variables defined in the Theme. --- .../src/codemods/template/migrate-theme-to-var.ts | 4 ++++ .../src/codemods/template/migrate.test.ts | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/packages/@tailwindcss-upgrade/src/codemods/template/migrate-theme-to-var.ts b/packages/@tailwindcss-upgrade/src/codemods/template/migrate-theme-to-var.ts index 6f7a3ece1fa0..d6d862d6242a 100644 --- a/packages/@tailwindcss-upgrade/src/codemods/template/migrate-theme-to-var.ts +++ b/packages/@tailwindcss-upgrade/src/codemods/template/migrate-theme-to-var.ts @@ -193,6 +193,10 @@ export function createConverter(designSystem: DesignSystem, { prettyPrint = fals let variable = `--${keyPathToCssProperty(toKeyPath(path))}` as const if (!designSystem.theme.get([variable])) return null + if (designSystem.theme.prefix) { + return `--${designSystem.theme.prefix}-${variable.slice(2)}` + } + return variable } diff --git a/packages/@tailwindcss-upgrade/src/codemods/template/migrate.test.ts b/packages/@tailwindcss-upgrade/src/codemods/template/migrate.test.ts index 216be87e35a7..49a40d016834 100644 --- a/packages/@tailwindcss-upgrade/src/codemods/template/migrate.test.ts +++ b/packages/@tailwindcss-upgrade/src/codemods/template/migrate.test.ts @@ -64,6 +64,11 @@ describe.each([['default'], ['with-variant'], ['important'], ['prefix']])('%s', // non-negative version first so we can replace `-mt-[0px]` with `mt-[0px]`. ['mt-[0px]', 'mt-[0px]'], ['-mt-[0px]', 'mt-[0px]'], + + // Shorthand CSS Variables should be converted to the new syntax, even if + // the fallback contains functions. The fallback should also be migrated to + // the newest syntax. + ['bg-[--my-color,theme(colors.red.500)]', 'bg-(--my-color,var(--color-red-500))'], ])(testName, async (candidate, result) => { if (strategy === 'with-variant') { candidate = `focus:${candidate}` From 239d34c98b29f3c3382d92a82fefeeff6b0ab429 Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Fri, 30 May 2025 12:55:45 +0200 Subject: [PATCH 4/5] update changelog --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f1520caed4e..a4a36503cf62 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -- Nothing yet! +### Fixed + +- Upgrade: migrate arbitrary modifiers with values between `0..=1` to bare values `/[0.16]` -> `/16` ([#18184](https://github.com/tailwindlabs/tailwindcss/pull/18184)) +- Upgrade: migrate CSS variable shorthand if fallback value contains function call ([#18184](https://github.com/tailwindlabs/tailwindcss/pull/18184)) ## [4.1.8] - 2025-05-27 From 72be3ca5b25afca9b99a228a9c787d5cf8dd3991 Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Fri, 30 May 2025 15:29:09 +0200 Subject: [PATCH 5/5] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a4a36503cf62..7614097a3409 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed -- Upgrade: migrate arbitrary modifiers with values between `0..=1` to bare values `/[0.16]` -> `/16` ([#18184](https://github.com/tailwindlabs/tailwindcss/pull/18184)) +- Upgrade: migrate arbitrary modifiers with values without percentage sign to bare values `/[0.16]` -> `/16` ([#18184](https://github.com/tailwindlabs/tailwindcss/pull/18184)) - Upgrade: migrate CSS variable shorthand if fallback value contains function call ([#18184](https://github.com/tailwindlabs/tailwindcss/pull/18184)) ## [4.1.8] - 2025-05-27