Migrate negative arbitrary values to negative bare values (#18212)

This PR adds some improvements to the upgrade tool where it can now also
migrate negative arbitrary values to negative bare values.

We already had support for the positive version of this:
```diff
- mb-[32rem]
+ mb-128
```

But now it can also handle negative values:
```diff
- mb-[-32rem]
+ -mb-128
```

The only tricky part here is that we had to hoist the `-` sign. Before
this PR, we were actually generating `mb--128` and that is invalid so it
was thrown out.

## Test plan

1. Added a test to ensure that the negative values are correctly
transformed.
This commit is contained in:
Robin Malfait 2025-06-03 10:53:58 +02:00 • committed by GitHub
parent 191195af7e
commit b3fde17eac
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 14 additions and 1 deletions

View file

@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- 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))
- Upgrade: Migrate negative arbitrary values to negative bare values, e.g.: `mb-[-32rem]` → `-mb-128` ([#18212](https://github.com/tailwindlabs/tailwindcss/pull/18212))
## [4.1.8] - 2025-05-27

View file

@ -159,7 +159,12 @@ export function migrateArbitraryUtilities(
candidate.kind === 'arbitrary' ? candidate.value : (candidate.value?.value ?? null)
if (value === null) return
let spacingMultiplier = spacing.get(designSystem)?.get(value)
let spacingMultiplier = spacing.get(designSystem)?.get(value) ?? null
let rootPrefix = ''
if (spacingMultiplier !== null && spacingMultiplier < 0) {
rootPrefix = '-'
spacingMultiplier = Math.abs(spacingMultiplier)
}
for (let root of Array.from(designSystem.utilities.keys('functional')).sort(
// Sort negative roots after positive roots so that we can try
@ -167,6 +172,8 @@ export function migrateArbitraryUtilities(
// `-mt-[0px]` can be translated to `mt-[0px]`.
(a, z) => Number(a[0] === '-') - Number(z[0] === '-'),
)) {
if (rootPrefix) root = `${rootPrefix}${root}`
// Try as bare value
for (let replacementCandidate of parseCandidate(designSystem, `${root}-${value}`)) {
yield replacementCandidate

View file

@ -69,6 +69,11 @@ describe.each([['default'], ['with-variant'], ['important'], ['prefix']])('%s',
// 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))'],
// Both the positive and negative versions of arbitrary utilities should be
// converted to the bare value version.
['mb-[32rem]', 'mb-128'],
['mb-[-32rem]', '-mb-128'],
])(testName, async (candidate, result) => {
if (strategy === 'with-variant') {
candidate = `focus:${candidate}`