Skip to content

Conversation

RobinMalfait
Copy link
Member

@RobinMalfait RobinMalfait commented Oct 10, 2025

This PR further improves the canonicalization of units in Tailwind CSS to increase the amount of similar candidates that can be converted to their canonical form.

This also introduces a rem option to the canonicalizeCandidates([…], { rem: 16 }). If this is passed with a pixel value, then rem units will be converted to px values. This is not enabled by default while running upgrades, but this can be used (e.g.: in intellisense).

This allows us to migrate mt-[16px] to mt-4 (assuming --spacing: 0.25rem is defined). Rem to px value migrations are not safe by default (because it depends on the root font size), but Intellisense can use them to provide a suggestion because in most cases that is what you want.

Internally this required a refactor because we now need the rem value as well. This introduced a SignatureOptions interface to make sure that we have a single stable object that can be passed around and that all the caches exist per SignatureOptions object. This means that you can call canonicalizeCandidates with different rem values without influencing other options.

As a user, you don't have to worry about making this second object stable, that will happen internally already.

Usage example:

designSystem.canonicalizeCandidates(['m-[16px]'])              // m-[16px]
designSystem.canonicalizeCandidates(['m-[16px]'], { rem: 16 }) // m-4 
designSystem.canonicalizeCandidates(['m-[16px]'], { rem: 64 }) // m-1

Test plan

  1. Made sure that existing tests pass
  2. Added new tests for when you pass in a rem value
  3. Also made sure that calling without rem value or a different value after the previous calls don't touch shared caches.

We will normalize units to their canonical form, this is an initial step
for allowing `rem` to `px` conversion as well.

in, cm, mm, q, pc, pt   → px
grad, rad, turn         → deg
ms                      → s
khz                     → hz

Already provided the option to pass in a `rem` value. Once passed in, we
will convert `rem` to `px` as well.
+ Expose a `CanonicalizeOptions`
This allows us to migrate `rem` to `px` when provided
The `SignatureOptions` will contain the `DesignSystem` in addition to
other potential options.

Already added the `rem` option (naming up for debate) to canonicalize
`rem` to `px` values if provided.
Instead of a top-level `DesignSystem`, we can use the
`SignatureOptions`. We can create `CanonicalizeOptions` or similar in
the future that contains `SignatureOptions` _if_ we need values while
canonicalizing values but aren't needed when creating a signature. Just
didn't want to add this as long as we don't need it.

This also changes the APIs for utility and variant canonicalization
steps. The APIs look like this:

```ts
type VariantCanonicalizationFunction = (variant: Variant, options: SignatureOptions) => Variant | Variant[]
type UtilityCanonicalizationFunction = (candidate: Candidate, options: SignatureOptions) => Candidate
```
@RobinMalfait RobinMalfait force-pushed the feat/canonicalize-dimensions branch from 619ccdc to edd6b21 Compare October 10, 2025 14:03
@RobinMalfait RobinMalfait marked this pull request as ready for review October 10, 2025 15:24
@RobinMalfait RobinMalfait requested a review from a team as a code owner October 10, 2025 15:24
@RobinMalfait RobinMalfait merged commit c67c0c5 into main Oct 10, 2025
7 checks passed
@RobinMalfait RobinMalfait deleted the feat/canonicalize-dimensions branch October 10, 2025 15:45
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.

2 participants