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> |
||
|---|---|---|
| .. | ||
| @tailwindcss-cli | ||
| @tailwindcss-node | ||
| @tailwindcss-postcss | ||
| @tailwindcss-standalone | ||
| @tailwindcss-upgrade | ||
| @tailwindcss-vite | ||
| internal-example-plugin | ||
| tailwindcss | ||
| tsconfig.base.json | ||