You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Some commits look like a lot of changes, but they just move things
around, so best to use `?w=1` when viewing commit by commit.
This PR adds a new feature to the `designSystem.canonicalizeCandidates`
to collapse multiple utilities to fewer utilities. To make this
possible, we also have to convert some logical properties to physical
properties (controllable via an option).
```ts
ds.canonicalizeCandidates(['w-4', 'h-4'], {
collapse: true // Default `true`
logicalToPhysical: true // Default `true`
}) // → ['size-4']
```
We can already compute the signature of each utility, where if two
utilities have the same signature they are considered the same.
However it's kind of impossible to generate all combinations of all
utilities ever to figure out if there is a potential collapse possible.
Even if we just focus on the incoming list of candidates, there could
still be a lot of classes. So instead we have to be a bit more clever.
First, we group candidates together by the used variants and if the
important `!` flag was used. We can improve this in the future, but for
now we won't even try to combine `hover:w-4 h-4`.
Next, for each candidate, we figure out which property and value it
uses. We can build up a lookup table for this. We already did this
process for all utilities in the system as well.
The lookup table for `w-4 h-4 p-4` might look something like this.
```json
{
"width": {
"16px": ["w-4", "size-4"],
},
"height": {
"16px": ["h-4", "size-4"],
},
"padding": {
"16px": ["p-4"],
}
}
```
Next, we can build groups of candidates where an intersection exists in
the lookup table. In the example above, we can see that `w-4` and `h-4`
both map to `size-4` for the value `16px`. So we can group these two
candidates. The `p-4`d doesn't intersect with anything else, so it
remains alone. This also means that we only have to generate
combinations for two candidates (2^2 = 4) instead of three (2^3 = 8). In
practice, your class list might have many classes, so keeping this
number low is important.
When we generate combinations, we will generate the most amount of
candidates first so we have the largest collapse possible. We also stop
when we reach <= 1 combinations because we need at least two candidates
to collapse.
Since this uses the internal design system, if you have custom
`@utility`s, this will work as expected.
```css
@Utility example {
@apply border rounded p-4;
}
```
If you then use:
```html
<div class="border m-0 rounded p-4"></div>
```
Then we can collapse this to:
```html
<div class="example m-0"></div>
```
But even if we used:
```html
<div class="border m-0 rounded pt-4 pb-4 px-4"></div>
```
It would still collapse to:
```html
<div class="example m-0"></div>
```
...because the `pt-4` and `pb-4` can collapse to `py-4`, and `py-4` and
`px-4` can collapse to `p-4`.
This is also where that logical to physical conversion comes into play,
because while `pt-4` and `pb-4` set the physical `padding-top` and
`padding-bottom` properties. The `py-4` utility sets the logical
`padding-block` property. So we internally transform `padding-block` to
the `padding-top` and `padding-bottom` physical properties. The funny
thing is that this logical to physical conversion actually means that we
will convert `pt-4` and `pb-4` from _physical_ to _logical_ properties,
because we converted to `py-4`...
In _most_ cases it's fine, and even preferred to use `py-1` over `pt-1
pb-1`, but in case it's not, then you can disable the
`logicalToPhysical` option.
## Test plan
Added some dedicated tests for this new functionality.
0 commit comments