tailwindcss/packages/@tailwindcss-upgrade
Robin Malfait 0d3e13ec60
Migrate arbitrary values to built-in values (#14841)
This PR adds a migration where we detect arbitrary variants and try to
upgrade them to built-in variants.

For example, if you are using `[[data-visible]]:flex`, we can convert it
to `data-visible:flex`. We can also upgrade more advanced examples such
as `has-[[data-visible]]:flex` to a compound variant which becomes
`has-data-visible:flex`.

A table of example migrations:

| Before | After |
| ------------------------------------------ |
---------------------------------- |
| `[[data-visible]]:flex` | `data-visible:flex` |
| `[&[data-visible]]:flex` | `data-visible:flex` |
| `[[data-visible]&]:flex` | `data-visible:flex` |
| `[[data-url*="example"]]:flex` | `data-[url*="example"]:flex` |
| `[[data-url$=".com"_i]]:flex` | `data-[url$=".com"_i]:flex` |
| `[[data-url$=.com_i]]:flex` | `data-[url$=.com_i]:flex` |
| `[&:is([data-visible])]:flex` | `data-visible:flex` |
| `has-[[data-visible]]:flex` | `has-data-visible:flex` |
| `has-[&:is([data-visible])]:flex` | `has-data-visible:flex` |
| `has-[[data-slot=description]]:flex` |
`has-data-[slot=description]:flex` |
| `has-[&:is([data-slot=description])]:flex` |
`has-data-[slot=description]:flex` |
| `has-[[aria-visible="true"]]:flex` | `has-aria-visible:flex` |
| `has-[[aria-visible]]:flex` | `has-aria-[visible]:flex` |

We can also convert combinators from `[&>[data-visible]]:flex` to just
`*:data-visible:flex` and `[&_[data-visible]]:flex` to
`**:data-visible:flex`.

| Before | After |
| --- | --- |
| `[&>[data-visible]]:flex` | `*:data-visible:flex` |
| `[&_>_[data-visible]]:flex` | `*:data-visible:flex` |
| `[&_[data-visible]]:flex` | `**:data-visible:flex` |

Additionally, if you have complex selectors with `:not()`, we can
convert this to a compound `not-*` variant in some cases as well:

| Before | After |
| --- | --- |
| `[&:nth-child(2)]:flex` | `nth-2:flex` |
| `[&:not(:nth-child(2))]:flex` | `not-nth-2:flex` |

If some of the values in `nth-child(…)` are a bit too complex, then we
still try to convert them but to arbitrary values instead.

| Before | After |  
| --- | --- |
| `[&:nth-child(-n+3)]:flex` | `nth-[-n+3]:flex` |
| `[&:not(:nth-child(-n+3))]:flex` | `not-nth-[-n+3]:flex` |

This also implements some optimizations around `even` and `odd`:

| Before | After |
| --- | --- |
| `[&:nth-child(odd)]:flex` | `odd:flex` |
| `[&:not(:nth-child(odd))]:flex` | `even:flex` |
| `[&:nth-child(even)]:flex` | `even:flex` |
| `[&:not(:nth-child(even))]:flex` | `odd:flex` |


Some examples that stay as-is:

- `has-[&>[data-visible]]:flex` we can't upgrade this one because
`has-*` is not a valid variant.
- `has-[[data-visible][data-dark]]:flex` we can't upgrade this one
because `[data-visible][data-dark]` has to be on the same element. If we
convert this to `has-data-visible:has-data-dark:flex` then this
condition will be true if an element exists with `data-visible` and
another element exists with `data-dark` but we don't guarantee that they
are the same element.

---

Running this on the Catalyst codebase results in some updates that look
like this:

<img width="676" alt="image"
src="https://github.com/user-attachments/assets/6f0ff21d-5037-440b-9b80-0997ab0c11dd">
<img width="397" alt="image"
src="https://github.com/user-attachments/assets/8f0856fa-1709-404a-ac34-7d8c661fa799">

---------

Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-11-11 12:44:13 +01:00
..
2024-09-18 16:45:43 +02:00

Tailwind CSS

A utility-first CSS framework for rapidly building custom user interfaces.

Build Status Total Downloads Latest Release License


Documentation

For full documentation, visit tailwindcss.com.

Community

For help, discussion about best practices, or any other conversation that would benefit from being searchable:

Discuss Tailwind CSS on GitHub

For chatting with others using the framework:

Join the Tailwind CSS Discord Server

Contributing

If you're interested in contributing to Tailwind CSS, please read our contributing docs before submitting a pull request.