Skip to content

Fix canonicalization resulting in empty list#19812

Merged
RobinMalfait merged 4 commits intomainfrom
fix/canonicalization-results-in-empty-list
Mar 17, 2026
Merged

Fix canonicalization resulting in empty list#19812
RobinMalfait merged 4 commits intomainfrom
fix/canonicalization-results-in-empty-list

Conversation

@RobinMalfait
Copy link
Member

This PR fixes a bug in the canonicalization process where if a few utilities collapse into a smaller one, and the smaller one is part of the original list, then it results in an empty list.

It will be more clear with an example. Let's say you have this setup:

w-[calc(1rem+0.25rem)] h-[calc(1rem+0.25rem)] size-5

The first step is that this will result in:

w-5 h-5 size-5

Then the w-5 h-5 can turn into size-5. But the existing size-5, can also be replaced by the size-5.

Internally, when we have a replacement, then we mark all the classes that can be replaced as "droppable", so they would be dropped from the list. But in this scenario we also marked size-5 as droppable, resulting in an empty list.

If an additional class existed:

w-[calc(1rem+0.25rem)] h-[calc(1rem+0.25rem)] size-5 flex

The result would be

flex

Instead of the expected:

size-5 flex

Test plan

  1. Existing tests pass
  2. Added new tests with and without an additional class

When we canonicalized a set of classes into a new class, then we marked
the existing classes as "droppable", meaning they should be removed in
favor of the replacement.

However, if the replacement is part of the existing class list, it means
that we would get rid of everything since the replacement is now marked
for removal.

Example:
```
w-[calc(1rem+0.25rem)] h-[calc(1rem+0.25rem)] size-5
```

The w-* and h-* would be collapsed into `w-5 h-5`. Then the result of
this would look like:
```
w-5 h-5 size-5
```

Now the `w-5 h-5` will be collapsed into `size-5`, and `size-5` itself
also can be replaced by itself. But this means that `size-5` is marked
for removal and the entire class list becomes empty.

This fixes that.
@RobinMalfait RobinMalfait requested a review from a team as a code owner March 17, 2026 11:49
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 17, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: f9b6c72d-a75f-4169-92ba-8acd507f88ba

📥 Commits

Reviewing files that changed from the base of the PR and between 99a5b8e and 8acc76d.

📒 Files selected for processing (1)
  • CHANGELOG.md
✅ Files skipped from review due to trivial changes (1)
  • CHANGELOG.md

Walkthrough

The change adds new tests to packages/tailwindcss/src/canonicalize-candidates.test.ts covering duplicate utilities, calc-based width/height values, and interactions with size-* and other classes. The collapseGroup implementation in packages/tailwindcss/src/canonicalize-candidates.ts was modified to add a replacement to results earlier, drop only non-replacement items from combinations, and preserve a replacement if it is already present in the combo. CHANGELOG.md was updated with a fix note about previous canonicalization producing an empty list in some cases.

🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main bug being fixed: a canonicalization process that was producing empty lists.
Description check ✅ Passed The description is well-detailed, providing a clear explanation of the bug, concrete examples, and the test plan for validating the fix.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

📝 Coding Plan
  • Generate coding plan for human review comments

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

CodeRabbit can use oxc to improve the quality of JavaScript and TypeScript code reviews.

Add a configuration file to your project to customize how CodeRabbit runs oxc.

@RobinMalfait RobinMalfait merged commit f302fce into main Mar 17, 2026
9 checks passed
@RobinMalfait RobinMalfait deleted the fix/canonicalization-results-in-empty-list branch March 17, 2026 12:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant