115 Commits

Author SHA1 Message Date
Robin Malfait
fe9fc9abba
Use resolveJsId when resolving tailwindcss/package.json (#15041)
This PR uses the `enhanced-resolve` instead of
`createRequire(…).resolve` which improves the usability when running the
upgrade tool locally using Bun.

While testing, we also noticed that it is not possible to use a
`cjs`-only plugin inside of an `esm` project. It was also not possible
to use an `esm`-only plugin inside of a `cjs` project.

# Test plan

We added integration tests in both the CLI (the CLI is an mjs project)
and in the PostCSS (where we can configure a `cjs` and `esm` PostCSS
config) integration tests where we created an `esm` and `cjs` based
project with 4 plugins (`cjs`-only, `esm`-only, and TypeScript based
plugins: `cts`-only and `mts`-only).
2024-11-19 18:39:49 +01:00
Jordan Pittman
b73c746e6e
Implement compat for <alpha-value> from v3 (#15033)
This implements backwards compatibility for colors that use the old
`<alpha-value>` feature from v3. We can do this by replacing
`<alpha-value>` with `1` because we use `color-mix` to actually apply
opacity modifiers in v4.
2024-11-19 10:01:45 -05:00
Philipp Spiess
b3d1cbb72f
Upgrade: Error when project is already using Tailwind CSS v4 (#15015)
In some local testing we ran the `@tailwindcss/upgrade` command twice in
a row. It would be great to get some feedback that this is not working,
so this PR now checks if it can resolve the installed version of
`tailwindcss` and if it can, it requires it to be < 4 (you can bypass
this check with `--force`).

---------

Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
2024-11-19 15:53:02 +01:00
Robin Malfait
38c9a881ac
Upgrade: don't show error during upgrade when analyzing external URL import (#15040)
This PR improves the output of the upgrade tool when we are handling
imports and the import happens to be an external URL.

External URLs shouldn't and can't be upgraded, so printing an error
message doesn't help the user.

Additionally, if an `@import` is using the `url(…)` function, then we
skip over it and continue with the rest of the imports.

| Before | After |
| --- | --- |
| <img width="1455" alt="image"
src="https://github.com/user-attachments/assets/1ee00ea4-68e1-4252-b1cf-30a04f608b75">
| <img width="1455" alt="image"
src="https://github.com/user-attachments/assets/da1f3eaf-dedb-4b1b-bf73-93bdfee65759">
|

Running this on github.com/parcel-bundler/parcel

| Before | After |
| -- | -- |
| <img width="1552" alt="image"
src="https://github.com/user-attachments/assets/89987444-8008-4edd-a907-6ad9276a86a0">
| <img width="1552" alt="image"
src="https://github.com/user-attachments/assets/cc2a34ae-ef17-4ad1-b06d-097874400b4d">
|
2024-11-19 15:52:30 +01:00
Robin Malfait
93f9c99027
Improve robustness when upgrading (#15038)
This PR improves the robustness when running the upgrade script.

Right now when you run it and if you run into issues, it could be that
an error with stack trace is printed in the terminal. This PR improves
most of the cases where this happens to ensure the output is easier to
parse as a human.

# Test plan:

Used SourceGraph to find some popular open source repositories that use
Tailwind and tried to run the upgrade tool on those repositories. If a
repository fails to upgrade, then that's a good candidate for this PR to
showcase the improved error messages.

github.com/docker/docs

| Before | After |
| --- | --- |
| <img width="1455" alt="image"
src="https://github.com/user-attachments/assets/ae28c1c1-8472-45a2-89f7-ed74a703e216">
| <img width="1455" alt="image"
src="https://github.com/user-attachments/assets/6bf4ec79-ddfc-47c4-8ba0-051566cb0116">
|

github.com/parcel-bundler/parcel

| Before | After |
| --- | --- |
| <img width="1455" alt="image"
src="https://github.com/user-attachments/assets/826e510f-df7a-4672-9895-8e13da1d03a8">
| <img width="1455" alt="image"
src="https://github.com/user-attachments/assets/a75146f5-bfac-4c96-a02b-be00ef671f73">
|

github.com/vercel/next.js

| Before | After |
| --- | --- |
| <img width="1455" alt="image"
src="https://github.com/user-attachments/assets/8d6c3744-f210-4164-b1ee-51950d44b349">
| <img width="1455" alt="image"
src="https://github.com/user-attachments/assets/b2739a9a-9629-411d-a506-3993a5867caf">
|
2024-11-19 14:29:51 +01:00
Robin Malfait
08c6c96f02
Improve multi-root @config linking (#15001)
This PR improves the discoverability of Tailwind config files when we
are trying to link them to your CSS files.

When you have multiple "root" CSS files in your project, and if they
don't include an `@config` directive, then we tried to find the Tailwind
config file in your current working directory.

This means that if you run the upgrade command from the root of your
project, and you have a nested folder with a separate Tailwind setup,
then the nested CSS file would link to the root Tailwind config file.

Visually, you can think of it like this:

```
.
├── admin
│   ├── src
│   │   └── styles
│   │       └── index.css       <-- This will be linked to (1)
│   └── tailwind.config.js      (2)
├── src
│   └── styles
│       └── index.css           <-- This will be linked to (1)
└── tailwind.config.js          (1)
```

If you run the upgrade command from the root of your project, then the
`/src/styles/index.css` will be linked to `/tailwind.config.js` which is
what we expect.

But `/admin/src/styles/index.css` will _also_ be linked to
`/tailwind.config.js`

With this PR we improve this behavior by looking at the CSS file, and
crawling up the parent tree. This mens that the new behavior looks like
this:

```
.
├── admin
│   ├── src
│   │   └── styles
│   │       └── index.css       <-- This will be linked to (2)
│   └── tailwind.config.js      (2)
├── src
│   └── styles
│       └── index.css           <-- This will be linked to (1)
└── tailwind.config.js          (1)
```

Now `/src/styles/index.css` will be linked to `/tailwind.config.js`, and
`/admin/src/styles/index.css` will be linked to
`/admin/tailwind.config.js`.

When we discover the Tailwind config file, we will also print a message
to the user to let them know which CSS file is linked to which Tailwind
config file.

This should be a safe improvement because if your Tailwind config file
had a different name, or if it lived in a sibling folder then Tailwind
wouldn't find it either and you already required a `@config "…";`
directive in your CSS file to point to the correct file.

In the unlikely event that it turns out that 2 (or more) CSS files
resolve to the same to the same Tailwind config file, then an upgrade
might not be safe and some manual intervention might be needed. In this
case, we will show a warning about this.

<img width="1552" alt="image"
src="https://github.com/user-attachments/assets/7a1ad11d-18c5-4b7d-9a02-14f0116ae955">


Test plan:
---

- Added an integration test that properly links the nearest Tailwind
config file by looking up the tree
- Added an integration test that resolves 2 or more CSS files to the
same config file, resulting in an error where manual intervention is
needed
- Ran it on the Tailwind UI codebase

Running this on Tailwind UI's codebase it looks like this:

<img width="1552" alt="image"
src="https://github.com/user-attachments/assets/21785428-5e0d-47f7-80ec-dab497f58784">

---------

Co-authored-by: Jordan Pittman <jordan@cryptica.me>
2024-11-18 16:43:44 +00:00
Robin Malfait
dd3441bf82
Add new in-* variant (#15025)
This PR adds a new `in-*` variant that allows you to apply utilities
when you are in a certain selector.

While doing research for codemods, we notice that some people use
`group-[]:flex` (yep, the arbitrary value is empty…). The idea behind is
that people want to know if you are in a `.group` or not.

Similarly, some people use `group-[]/name:flex` to know when you are in
a `.group/name` class or not.

This new `in-*` variant allows you to do that without any hacks.

If you want to check whether you are inside of a `p` tag, then you can
write `in-[p]:flex`. If you want to check that you are inside of a
`.group`, you can write `in-[.group]`.

This variant is also a compound variant, which means that you can write
`in-data-visible:flex` which generates the following CSS:
```css
:where([data-visible]) .in-data-visible\:flex {
  display: flex;
}
```

This variant also compounds with `not-*`, for example:
`not-in-[.group]:flex`.

Additionally, this PR also includes a codemod to convert `group-[]:flex`
to `in-[.group]:flex`.

---

This was proposed before for v3 in #13912

---------

Co-authored-by: Eloy Espinaco <eloyesp@gmail.com>
Co-authored-by: Jordan Pittman <jordan@cryptica.me>
2024-11-18 15:28:16 +00:00
Robin Malfait
4687777788
Migrate [&>*] to * variant, and [&_*] to ** variant (#15022)
This PR adds a migration to convert the `[&>*]` variant to the `*`
variant. Additionally this PR also converts the `[&_*]` variant to the
`**` variant.

We use this variant in Catalyst for example, and now that the
specificity is the same as `*`, we can use the more modern syntax
instead.


# Test plan:

Running this on Catalyst results in a diff like:
<img width="615" alt="image"
src="https://github.com/user-attachments/assets/f384885e-cae1-4b6b-80ab-85f76fa89a33">

<img width="833" alt="image"
src="https://github.com/user-attachments/assets/8a185e1d-0f1b-4fe6-9e06-ca7597534398">


Note: the swapped order of variants is another codemod at work

---------

Co-authored-by: Adam Wathan <adam.wathan@gmail.com>
2024-11-18 16:19:15 +01:00
Robin Malfait
3dc3bad781
Re-introduce automatic var injection shorthand (#15020)
This PR re-introduces the automatic var injection feature.

For some backstory, we used to support classes such as `bg-[--my-color]`
that resolved as-if you wrote `bg-[var(--my-color)]`.

The is issue is that some newer CSS properties accepts dashed-idents
(without the `var(…)`). This means that some properties accept
`view-timeline-name: --my-name;` (see:
https://developer.mozilla.org/en-US/docs/Web/CSS/view-timeline-name).

To make this a tiny bit worse, these properties _also_ accept
`var(--my-name-reference)` where the variable `--my-name-reference`
could reference a dashed-ident such as `--my-name`.

This makes the `bg-[--my-color]` ambiguous because we don't know if you
want `var(--my-color)` or `--my-color`.

With this PR, we bring back the automatic var injection feature as
syntactic sugar, but we use a different syntax to avoid the ambiguity.
Instead of `bg-[--my-color]`, you can now write `bg-(--my-color)` to get
the same effect as `bg-[var(--my-color)]`.

This also applies to modifiers, so `bg-red-500/[var(--my-opacity)]` can
be written as `bg-red-500/(--my-opacity)`. To go full circle, you can
rewrite `bg-[var(--my-color)]/[var(--my-opacity)]` as
`bg-(--my-color)/(--my-opacity)`.

---

This is implemented as syntactical sugar at the parsing stage and
handled when re-printing. Internally the system (and every plugin) still
see the proper `var(--my-color)` value.

Since this is also handled during printing of the candidate, codemods
don't need to be changed but they will provide the newly updated syntax.

E.g.: running this on the Catalyst codebase, you'll now see changes like
this:
<img width="542" alt="image"
src="https://github.com/user-attachments/assets/8f0e26f8-f4c9-4cdc-9f28-52307c38610e">

Whereas before we converted this to the much longer
`min-w-[var(--button-width)]`.

---

Additionally, this required some changes to the Oxide scanner to make
sure that `(` and `)` are valid characters for arbitrary-like values.

---------

Co-authored-by: Adam Wathan <adam.wathan@gmail.com>
2024-11-18 15:47:48 +01:00
depfu[bot]
22d36cc95b
Update tree-sitter-typescript 0.23.0 → 0.23.2 (minor) (#15026) 2024-11-18 10:23:22 +01:00
Robin Malfait
57f87be440
Resolve imports from CSS file (#15010)
This PR adds an improvement to the upgrade tool to make sure that if you
pass a single CSS file, that the upgrade tool resolves all the imports
in that file and processes them as well.


Test plan:
---

Created a project where `index.css` imports `other.css`. Another
`leave-me-alone.css` is created to proof that this file is _not_
changed. Running the upgrade guide using `index.css` also migrates
`other.css` but not `leave-me-alone.css`.

Here is a video so you don't have to manually create it:



https://github.com/user-attachments/assets/20decf77-77d2-4a7c-8ff1-accb1c77f8c1
2024-11-15 22:06:52 +01:00
Philipp Spiess
5edf6c7dc0
Ensure clients pin the tailwindcss version (#15011)
We noticed that in the current alpha 34 release, the `package.json` file
of the `@tailwindcss/node` package only defines `tailwindcss` as a dev
dependency. This makes it very easy for version mismatches to happen
when a v3 version (or an earlier v4 alpha for that matter) was installed
in the same project:

```json
{
  "name": "@tailwindcss/node",
  "version": "4.0.0-alpha.34",
  "description": "A utility-first CSS framework for rapidly building custom user interfaces.",
  "license": "MIT",
  "repository": {
    "type": "git",
    "url": "https://github.com/tailwindlabs/tailwindcss.git",
    "directory": "packages/@tailwindcss-node"
  },
  "bugs": "https://github.com/tailwindlabs/tailwindcss/issues",
  "homepage": "https://tailwindcss.com",
  "files": [
    "dist/"
  ],
  "publishConfig": {
    "provenance": true,
    "access": "public"
  },
  "exports": {
    ".": {
      "types": "./dist/index.d.ts",
      "import": "./dist/index.mjs",
      "require": "./dist/index.js"
    },
    "./require-cache": {
      "types": "./dist/require-cache.d.ts",
      "default": "./dist/require-cache.js"
    },
    "./esm-cache-loader": {
      "types": "./dist/esm-cache.loader.d.mts",
      "default": "./dist/esm-cache.loader.mjs"
    }
  },
  "devDependencies": {
    "tailwindcss": "4.0.0-alpha.34"
  },
  "dependencies": {
    "enhanced-resolve": "^5.17.1",
    "jiti": "^2.0.0-beta.3"
  },
  "scripts": {
    "build": "tsup-node",
    "dev": "pnpm run build -- --watch"
  }
}
```

Furthermore, we were trying to fix issues where our integration test
setup could not install `tailwindcss@3` because of how we did pnpm
overrides.

This PR fixes this by:

- Ensuring every client that calls into `tailwindcss` core marks it as a
version-pinned dependency. You are still required to install
`tailwindcss` in your project along side a client (e.g.
`@tailwindcss/vite`) but we now only use your installed version for
importing the respective `.css` files. For the core logic, we are now
requiring each package to use `tailwindcss` at the same version. This
should help resolve issues like
https://github.com/tailwindlabs/tailwindcss/discussions/14652
- We tried to eliminate the dependency on `tailwindcss` from the
`@tailwindcss/upgrade` package. Unfortunately this is not possible to do
right now because we need to load the CSS files from v4 to create the
right environment. In a future version we could bundle the required CSS
files with `@tailwidncss/upgrade` but it doesn't seem necessary for now.
- We then changed our integration test overrides to only override the
`tailwindcss` package that are dependencies of the known list of
packages that we have `tailwindcss` dependencies on: `@tailwindcss/node`
and `@tailwindcss/upgrade`. This ensures that we can install v3 of
`tailwindcss` in the integration tests and it will work. Something we
want to do for some upgrade tests.

# Test plan

Integration work again. Furthermore we added a quick setup with the CLI
using the local tarballs and ensured it works:

```bash
pnpm init
pnpm install ../../tailwindcss/dist/tailwindcss-cli.tgz 
pnpm install ../../tailwindcss/dist/tailwindcss.tgz 
echo '@import "tailwindcss";' > index.css
echo '<div class="underline"></div>' > index.html
pnpm tailwindcss -i index.css -o out.css
cat out.css
```
2024-11-15 17:18:48 +01:00
Philipp Spiess
953ecd2d19
Prepare v4.0.0-alpha.34 (#15002) 2024-11-14 18:23:40 +01:00
Philipp Spiess
890f18de93
Add codemod and interop for legacy container component configu (#14999)
This PR adds support for handling v3 [`container` customizations
](https://tailwindcss.com/docs/container#customizing). This is done by
adding a custom utility to extend the core `container` utility. A
concrete example can be taken from the added integration test.

### Input

```ts
/** @type {import('tailwindcss').Config} */
export default {
  content: ['./src/**/*.html'],
  theme: {
    container: {
      center: true,
      padding: {
        DEFAULT: '2rem',
        '2xl': '4rem',
      },
      screens: {
        md: '48rem', // Matches a default --breakpoint
        xl: '1280px',
        '2xl': '1536px',
      },
    },
  },
}
```

### Output

```css
@import "tailwindcss";

@utility container {
  margin-inline: auto;
  padding-inline: 2rem;

  @media (width >= theme(--breakpoint-sm)) {
    max-width: none;
  }

  @media (width >= 48rem) {
    max-width: 48rem;
  }

  @media (width >= 1280px) {
    max-width: 1280px;
  }

  @media (width >= 1536px) {
    max-width: 1536px;
    padding-inline: 4rem;
  }
}
````


## Test Plan

This PR adds extensive tests to the compat layer as part of unit tests.
Additionally it does at a test to the codemod setup that shows that the
right `@utility` code is generated. Furthermore I compared the
implementation against v3 on both the compat layer and the custom
`@utility`:


https://github.com/user-attachments/assets/44d6cbfb-4861-4225-9593-602b719f628f
2024-11-14 12:19:21 -05:00
Robin Malfait
4079059420
Add missing layer(…) to imports above Tailwind directives (#14982)
This PR fixes an issue where imports above Tailwind directives didn't
get a `layer(…)` argument.

Given this CSS:
```css
@import "./typography.css";
@tailwind base;
@tailwind components;
@tailwind utilities;
```

It was migrated to:
```css
@import "./typography.css";
@import "tailwindcss";
```

But to ensure that the typography styles end up in the correct location,
it requires the `layer(…)` argument.

This PR now migrates the input to:
```css
@import "./typography.css" layer(base);
@import "tailwindcss";
```

Test plan:
---

Added an integration test where an import receives the `layer(…)`, but
an import that eventually contains `@utility` does not receive the
`layer(…)` argument. This is necessary otherwise the `@utility` will be
nested when we are processing the inlined CSS.

Running this on the Commit template, we do have a proper `layer(…)`
<img width="585" alt="image"
src="https://github.com/user-attachments/assets/538055e6-a9ac-490d-981f-41065a6b59f9">
2024-11-14 18:05:14 +01:00
Robin Malfait
8538ad859c
Ensure @config is injected in common ancestor sheet (#14989)
This PR fixes an issue where an `@config` was injected in a strange
location if you have multiple CSS files with Tailwind directives.

Let's say you have this setup:
```css
/* ./src/index.css */
@import "./tailwind-setup.css";

/* ./src/tailwind-setup.css */
@import "./base.css";
@import "./components.css";
@import "./utilities.css";

/* ./src/base.css */
@tailwind base;

/* ./src/components.css */
@tailwind components;

/* ./src/utilities.css */
@tailwind utilities;
```

In this case, `base.css`, `components.css`, and `utilities.css` are all
considered Tailwind roots because they contain Tailwind directives or
imports.

Since there are multiple roots, the nearest common ancestor should
become the tailwind root (where `@config` is injected). In this case,
the nearest common ancestor is `tailwind-setup.css` (not `index.css`
because that's further away).

Before this change, we find the common ancestor between `base.css` and
`components.css` which would be `index.css` instead of
`tailwind-setup.css`.

In a next iteration, we compare `index.css` with `utilities.css` and
find that there is no common ancestor (because the `index.css` file has
no parents). This resulted in the `@config` being injected in
`index.css` and in `utilities.css`.

Continuing with the rest of the migrations, we migrate the `index.css`'s
`@config` away, but we didn't migrate the `@config` from
`utilities.css`.

With this PR, we don't even have the `@config` in the `utilities.css`
file anymore.

Test plan
---

1. Added an integration test with a non-migrateable config file to
ensure that the `@config` is injected in the correct file.
2. Added an integration test with a migrateable config file to ensure
that the CSS config is injected in the correct file. h/t @philipp-spiess
3. Ran the upgrade on the https://commit.tailwindui.com project and
ensured that
1. The `@config` does not exist in the `utilities.css` file (this was
the first bug we solved)
  2. The `@config` is replaced in the `tailwind.css` file correctly.

<img width="592" alt="image"
src="https://github.com/user-attachments/assets/02e3f6ea-a85d-46c2-ac93-09f34ac4a4b8">

<img width="573" alt="image"
src="https://github.com/user-attachments/assets/e372eb5f-5732-4052-ab39-096ba7970ff6">
2024-11-14 11:48:31 +01:00
Robin Malfait
49484f0491
Do not migrate legacy classes with custom values (#14976)
This PR fixes an issue where we migrated classes such as `rounded` to
`rounded-sm` (see:
https://github.com/tailwindlabs/tailwindcss/pull/14875)

However, if you override the values in your `tailwind.config.js` file,
then the migration might not be correct.

This PR makes sure to only migrate the classes if you haven't overridden
the values in your `tailwind.config.js` file.

---------

Co-authored-by: Philipp Spiess <hello@philippspiess.com>
2024-11-14 11:31:05 +01:00
Adam Wathan
437579d3f0
Prepare v4.0.0-alpha.33 release (#14967)
Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-11-11 20:28:41 -05:00
Adam Wathan
7da9272d0f
Prepare v4.0.0-alpha.32 (#14954)
Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-11-11 11:05:22 -05:00
Robin Malfait
292efa5daa
Remove the negative flag from the Candidate AST (#14938)
This PR removes the `negative` flag from the `Candidate` AST. The system
itself doesn't this information at all, but it's up to each plugin to
handle the `negative` flag themselves.

This also means that if you _don't_ handle it, that `foo` and `-foo`
results in the same CSS output.

To make sure that the negative version of utilities that supported it
still work, this PR also adds the negative versions as separate
utilities. E.g.: `-scale` is registered in addition to `scale`.

This is an internal refactor only, and doesn't change any behavior.

---------

Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-11-11 10:46:53 -05:00
Robin Malfait
d325e70496
Convert , to in grid-cols-[…], grid-rows-[…], and object-[…] (#14927)
This PR converts legacy commas in arbitrary values to spaces.

In Tailwind CSS v3, we allowed commas in arbitrary values for
`grid-cols-[…]`, `grid-rows-[…]`, and `object-[…]` for backwards
compatibility. The underlying CSS value did use spaces instead of
commas.

This PR adds a code mod where convert the commas to spaces when we see
them.


Test plan:
---

Running this on Catalyst it goes from this:

<img width="393" alt="image"
src="https://github.com/user-attachments/assets/03cbda73-41f9-4601-b77a-5b511226b876">

To the expected value of:

<img width="376" alt="image"
src="https://github.com/user-attachments/assets/dd9bbe01-5eb1-4340-937b-70c435e7e4f0">

---------

Co-authored-by: Adam Wathan <adam.wathan@gmail.com>
2024-11-11 10:26:37 -05:00
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
Adam Wathan
56288a318a
Remove input borders by default (#14929)
This PR reverts a change we made for v4 that added borders to inputs by
default. It feels like we have to go further than this for this to
actually be useful to anyone, and since there were no borders in v3 it's
also a breaking change.

If we wanted to make form elements look more "normal" out of the box I
think we need to do something more like this:

https://play.tailwindcss.com/icCwFLVp4z?file=css

But it's a huge rabbit hole and there are so many stupid details to get
right that it feels like an insurmountable task, and if we can't go all
the way with it it's better to just maximize compatibility with v3.

---------

Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-11-08 15:29:41 -05:00
Adam Wathan
bcddc81f66
Replace outline-none with outline-hidden, add new outline-none (#14926)
This PR renames the existing `outline-none` utility to `outline-hidden`,
and adds a new simpler `outline-none` utility that just sets
`outline-style: none`.

The existing `outline-none` utility doesn't actually set `outline:
none`, and instead creates a 2px invisible outline:

```css
.outline-none {
  outline: 2px solid transparent;
  outline-offset: 2px;
}
```

We implemented it this way because people often use `outline: none` to
hide focus rings and replace them with custom shadow-based focus rings,
without realizing that that approach leads to no visible focus ring in
forced colors mode because box shadows aren't rendered in forced colors
mode.

While this is sort of helpful and clever, it can be a pain when you
really do need `outline: none`, and I think it feels surprising in
hindsight to hijack the name of an existing CSS property value and make
it mean something else.

The name `outline-hidden` feels better because it's a new keyword that
CSS doesn't use for outlines, and implies that perhaps there's a bit
more going on than just setting `outline-style: none`.

This PR includes a codemod to convert any existing use of `outline-none`
to `outline-hidden`, and we will be sure to explain what
`outline-hidden` does for you in the v4 documentation.

Manually tested this in the Vite playground to make sure it behaves as
expected 👍

---------

Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-11-08 20:03:12 +01:00
Robin Malfait
3fb49bb0ee
Fix theme(…/15%) to only apply when used on its own (#14922)
This PR fixes an issue where our codemod migrations can convert
`bg-[theme(colors.white/15%)]` to `bg-[var(--color-white)]/15` where the
`15%` from within the `theme(…)` is converted to a candidate modifier
(at the end).

The idea was that if the `theme(…)` is used with a modifier, then it can
only be used with colors. If a candidate uses it, it also means that a
color was used and we can use `/15` instead.

However this is not true if it is used as part of a bigger value. E.g.:
`shadow-[shadow:inset_0_0_0_1px_theme(colors.white/15%)]` would be
converted to `shadow-[inset_0_0_0_1px_var(--color-white)]/15` which is
not correct because the value isn't a color, the color is _part_ of the
value.

In this case, we make sure that the `theme(…)` is the only AST node in
the value, and if it is we can safely do the conversion. If there are
other AST nodes we keep the `theme(…)` call.

---------

Co-authored-by: Adam Wathan <adam.wathan@gmail.com>
2024-11-08 16:05:30 +00:00
Philipp Spiess
aaa32e23e2
Allow newlines and tabs in the argument list of the theme() function (#14917)
We noticed an issue that the `theme()` function wourld not properly
parse in CSS if you split the argument list over multiple lines. This is
fixed by treating `\n` and `\t` the same as space:

```css
.custom-font {
  font-family: theme(
    fontFamily.unknown,
    Helvetica Neue,
    Helvetica,
    sans-serif
  );
}
```

## Test plan

Added tests, but also tried it in the Vite example:

<img width="1995" alt="Screenshot 2024-11-08 at 13 46 09"
src="https://github.com/user-attachments/assets/f9bf94b0-3f9b-4334-8911-9190987e2df5">
2024-11-08 10:14:11 -05:00
Robin Malfait
99c4c04c54
Fix glob pattern hoisting on Windows (#14904)
This ensures our glob hoisting mechanism (see #14896) works on Windows
when performing an upgrade.

---------

Co-authored-by: Jordan Pittman <jordan@cryptica.me>
2024-11-07 15:31:06 -05:00
Philipp Spiess
95c4877200
Upgrade: Migrate spacing scale (#14905)
This PR adds migrations for the recent changes to the `--spacing` scale
done in #12263.

There are a few steps that we do to ensure we have the best upgrade
experience:

- If you are overwriting the `spacing` theme with custom values, we now
check if the new values are multiplies of the default spacing scale.
When they are, we can safely remove the overwrite.
- If you are extending the `spacing` theme, we will unset the default
`--spacing` scale and only use the values you provided.
- Any `theme()` function calls are replaced with `calc(var(--spacing) *
multiplier)` unless the values are extending the default scale.

One caveat here is for `theme()` key which can not be replaced with
`var()` (e.g. in `@media` attribute positions). These will not be able
to be replaced with `calc()` either so the following needs to stay
unmigrated:

```css
@media (max-width: theme(spacing.96)) {
  .foo {
    color: red;
  }
}
```

## Test plan

We are mainly testing two scenarios: The JS config _extends_ the
`spacing` namespace and the JS config _overwrites_ the `spacing`
namespace. For both cases we have added an integration test each to
ensure this works as expected. The test contains a mixture of keys (some
of it matching the default multiples, some don't, some have different
scales, and some use non-numeric identifiers). In addition to asserting
on the created CSS `@theme`, we also ensure that `theme()` calls are
properly replaced.

---------

Co-authored-by: Adam Wathan <adam.wathan@gmail.com>
Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-11-07 14:25:21 -05:00
Adam Wathan
28e46badf7
Rename --font-size-* variables to --text-* (#14909)
This PR updates all of the `--font-size-*` variables to `--text-*`
instead to closer match the utility names.

```diff
  @theme {
-   --font-size-xs: 0.75rem;
-   --font-size-xs--line-height: 1rem;
-   --font-size-sm: 0.875rem;
-   --font-size-sm--line-height: 1.25rem;
-   --font-size-base: 1rem;
-   --font-size-base--line-height: 1.5rem;
-   --font-size-lg: 1.125rem;
-   --font-size-lg--line-height: 1.75rem;
-   --font-size-xl: 1.25rem;
-   --font-size-xl--line-height: 1.75rem;

    /* ... */
  
+   --text-xs: 0.75rem;
+   --text-xs--line-height: 1rem;
+   --text-sm: 0.875rem;
+   --text-sm--line-height: 1.25rem;
+   --text-base: 1rem;
+   --text-base--line-height: 1.5rem;
+   --text-lg: 1.125rem;
+   --text-lg--line-height: 1.75rem;
+   --text-xl: 1.25rem;
+   --text-xl--line-height: 1.75rem;

    /* ... */
  }
```

This is part of a bigger set of changes where we're renaming other theme
variables as well with the same goals, since many existing theme
variables like `--shadow-*` and `--radius-*` are already not using the
explicit CSS property name.

---------

Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
Co-authored-by: Philipp Spiess <hello@philippspiess.com>
Co-authored-by: Jordan Pittman <jordan@cryptica.me>
2024-11-07 14:08:06 -05:00
Robin Malfait
75eeed85b6
Fix crash during upgrade when content globs escape root of project (#14896)
This PR fixes an issue where globs in you `content` configuration escape
the current "root" of the project.

This can happen if you have a folder, and you need to look up in the
tree (e.g.: when looking at another package in a monorepo, or in case of
a Laravel project where you want to look at mail templates).

This applies a similar strategy we already implement on the Rust side.

1. Expand braces in the globs
2. Move static parts of the `pattern` to the `base` of the glob entry
object

---

Given a project setup like this:
```
.
├── admin
│   ├── my-tailwind.config.ts
│   └── src
│       ├── abc.jpg
│       ├── index.html
│       ├── index.js
│       └── styles
│           └── input.css
├── dashboard
│   ├── src
│   │   ├── index.html
│   │   ├── index.js
│   │   ├── input.css
│   │   └── pickaday.css
│   └── tailwind.config.ts
├── package-lock.json
├── package.json
├── postcss.config.js
└── unrelated
    └── index.html

7 directories, 14 files
```


If you then have this config:
```ts
// admin/my-tailwind.config.ts
export default {
  content: {
    relative: true,
    files: ['./src/**/*.html', '../dashboard/src/**/*.html'],
                            //  ^^  this is the important part, which escapes
                            //      the current root of the project.
  },
  theme: {
    extend: {
      colors: {
        primary: 'red',
      },
    },
  },
}
```


Then before this change, running the command looks like this:
<img width="1760" alt="image"
src="https://github.com/user-attachments/assets/60e2dfc7-3751-4432-80e3-8b4b8f1083d4">


After this change, running the command looks like this:
<img width="1452" alt="image"
src="https://github.com/user-attachments/assets/5c47182c-119c-4732-a253-2dace7086049">

---------

Co-authored-by: Philipp Spiess <hello@philippspiess.com>
2024-11-07 12:22:25 +00:00
Robin Malfait
462308d8d7
Sort upgraded CSS (#14866)
During the migration process, a lot of changes to the CSS file happen.
Some parts are converted, some parts are deleted and some new CSS is
added.

To make sure we are generating a sensible and good looking CSS file, we
will sort the final CSS and pretty print it.

The order we came up with looks like this:

```css
/* Imports */
@import "tailwindcss";
@import "../other.css";

/* Configuration */
@config "../path/to/tailwindcss.config.js";

@plugin "my-plugin-1";
@plugin "my-plugin-2";

@source "./foo/**/*.ts";
@source "./bar/**/*.ts";

@variant foo {}
@variant bar {}

@theme {}

/* Border compatibility CSS */
@layer base {}

/* Utilities */
@utility foo {}
@utility bar {}

/* Rest of your own CSS if any */
```

---------

Co-authored-by: Philipp Spiess <hello@philippspiess.com>
2024-11-07 12:04:52 +00:00
Adam Wathan
26638af3ef
Rename --width-* namespace to --container-* (#14898)
This PR renames all of the `--width-*` variables to `--container-*` to
better communicate the purpose of these tokens as layout container
sizes. These are the values that were historically stored under
`maxWidth` in the v3 and earlier eras, and were also re-used by the
container queries plugin.

The name `--container-*` feels like a better match alongside the
`--breakpoint-*` namespace and since these both serve that same sort of
purpose it makes sense to me that the name should be optimized for
feeling "right" in that context.

I like that this also sort of advertises Tailwind's support for
container queries directly in the CSS variables themselves, and helps
people understand what these are really intended to be used for.

---------

Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-11-06 20:50:30 -05:00
Robin Malfait
d099f8bda6
Migrate default utilities to have a value suffix (#14875)
This PR adds a migration for migrating the changes we implemented in
https://github.com/tailwindlabs/tailwindcss/pull/14849

This is the migration we perform:

| Old               | New                |
| ----------------- | ------------------ |
| `shadow`          | `shadow-sm`        |
| `shadow-sm`       | `shadow-xs`        |
| `shadow-xs`       | `shadow-2xs`       |
| `inset-shadow`    | `inset-shadow-sm`  |
| `inset-shadow-sm` | `inset-shadow-xs`  |
| `inset-shadow-xs` | `inset-shadow-2xs` |
| `drop-shadow`     | `drop-shadow-sm`   |
| `drop-shadow-sm`  | `drop-shadow-xs`   |
| `rounded`         | `rounded-sm`       |
| `rounded-sm`      | `rounded-xs`       |
| `blur`            | `blur-sm`          |
| `blur-sm`         | `blur-xs`          |

Also added an integration test to ensure that `shadow` is properly
migrated to `shadow-sm`, and doesn't get migrated to `shadow-xs`
(because `shadow-sm` is migrated to `shadow-xs`).
2024-11-06 12:28:38 +01:00
Adam Wathan
8bd3c85420
Derive all font-weight values from theme (#14883)
This PR removes all of the static `font-weight` utilities that were
previously hard-coded into the framework in favor of deriving those
utilities from the `--font-weight-*` theme values instead.

Biggest motivation for this is giving people a way to explicitly disable
font-weight utilities they don't want to use in their project, which
previously wasn't possible.

---------

Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-11-05 16:06:47 -05:00
Adam Wathan
c50de9384a
Replace default explicit spacing scale with multiplier system (#14857)
This PR replaces the default spacing scale (`--spacing-*`) with a
generative system based on a default spacing _unit_.

Instead of the default theme containing values like `--spacing-4`,
`--spacing-6`, `--spacing-8`, etc., instead we just define a single
`--spacing` value:

```css
@theme {
  --spacing: 0.25rem;
}
```

Utilities like `px-4` are derived from this unit by multiplying it by
the value in the utility (4 in this case):

```css
.px-4 {
  padding-inline: calc(var(--spacing) * 4);
}
```

The biggest consequence of this change is that every value is available
now, rather than just the explicitly configured values.

This means utilities like `px-42` will work now, whereas prior to this
PR only `px-40` and `px-44` were valid utilities. I personally found it
very difficult to know which values actually existed at the higher end
of the scale without IntelliSense, and in practice even when working
with a skilled designer like [Steve](https://x.com/steveschoger) who
helped design Tailwind's default spacing scale, I'd very often need to
break out of it to implement a design, and trying to round to a value
that was in the scale made the design worse, not better.

This PR allows you to use any whole number, as well as decimal numbers
that are multiples of `0.25` to ensure classes like `px-1.5` continue to
work. While this means you can now technically do things like
`pt-97.25`, I think the presence of the fractional value will be enough
of a signal to developers that they are doing something a little
unusual, and they can use their judgment as to whether they are making
the right decision or not.

I'll update this PR with a lot more detail when I have a chance, as
there are a few other things to explain like:

- Unifying all of the values for
width/min-width/max-width/height/min-height/max-height utilities
- Deriving numeric line-height values from the spacing multiplier
instead of a separate line-height scale
- Using `--spacing: initial` to disable the multiplier
- How you can still use an explicit spacing scale and ignore this change
- How we plan to use IntelliSense to surface a more curated set of
spacing values even if smaller increments work when you type them
explicitly

---------

Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-11-05 15:22:50 -05:00
Robin Malfait
894bf9f5ef
Support migrating projects with multiple config files (#14863)
When migrating a project from Tailwind CSS v3 to Tailwind CSS v4, then
we started the migration process in the following order:

1. Migrate the JS/TS config file
2. Migrate the source files (found via the `content` option)
3. Migrate the CSS files

However, if you have a setup where you have multiple CSS root files
(e.g.: `frontend` and `admin` are separated), then that typically means
that you have an `@config` directive in your CSS files. These point to
the Tailwind CSS config file.

This PR changes the migration order to do the following:

1. Build a tree of all the CSS files
2. For each `@config` directive, migrate the JS/TS config file
3. For each JS/TS config file, migrate the source files

If a CSS file does not contain any `@config` directives, then we start
by filling in the `@config` directive with the default Tailwind CSS
config file (if found, or the one passed in). If no default config file
or passed in config file can be found, then we will error out (just like
we do now)

---------

Co-authored-by: Adam Wathan <adam.wathan@gmail.com>
2024-11-04 16:52:11 +00:00
depfu[bot]
df6dfb012c
Update tree-sitter 0.21.1 → 0.22.0 (major) (#14858) 2024-11-04 15:14:46 +01:00
Robin Malfait
baed3aabe2
Migrate grid-cols-[subgrid] and grid-rows-[subgrid] to grid-cols-subgrid and grid-rows-subgrid (#14840)
This PR adds a migration to convert `grid-cols-[subgrid]` to
`grid-cols-subgrid` and `grid-rows-[subgrid]` to `grid-rows-subgrid`.
2024-11-01 20:25:53 +00:00
Robin Malfait
0b5736f1b2
Remove whitespace around , separator (#14838)
This PR is an improvement/fix by making sure that whitespace around the
`,` separator is removed when printing arbitrary values.

Before:
```diff
- <div class="grid-cols-[min(50%,theme(spacing.80))_auto]"></div>
+ <div class="grid-cols-[min(50%,_var(--spacing-80))_auto]"></div>
```

After:
```diff
- <div class="grid-cols-[min(50%,theme(spacing.80))_auto]"></div>
+ <div class="grid-cols-[min(50%,var(--spacing-80))_auto]"></div>
```

---------

Co-authored-by: Jordan Pittman <jordan@cryptica.me>
2024-10-31 10:15:52 +01:00
Robin Malfait
92007a5b23
Fix crash when using @source containing .. (#14831)
This PR fixes an issue where a `@source` crashes when the path
eventually resolves to a path ending in `..`.

We have to make sure that we canonicalize the path to make sure that we
are working with the real directory.

---------

Co-authored-by: Jordan Pittman <jordan@cryptica.me>
2024-10-30 16:24:48 -04:00
Robin Malfait
eb54dcdbfc
Install @tailwindcss/postcss next to tailwindcss (#14830)
This PR improves the PostCSS migrations to make sure that we install
`@tailwindcss/postcss` in the same bucket as `tailwindcss`.

If `tailwindcss` exists in the `dependencies` bucket, we install
`@tailwindcss/postcss` in the same bucket. If `tailwindcss` exists in
the `devDependencies` bucket, we install `@tailwindcss/postcss` in the
same bucket.

This also contains an internal refactor that normalizes the package
manager to make sure we can install a package to the correct bucket
depending on the package manager.

---------

Co-authored-by: Adam Wathan <adam.wathan@gmail.com>
2024-10-30 15:32:24 -04:00
depfu[bot]
840c9e65b9
Update postcss-selector-parser 6.1.2 → 7.0.0 (major) (#14834)
Here is everything you need to know about this upgrade. Please take a
good look at what changed and the test results before merging this pull
request.

### What changed?




#### ✳️ postcss-selector-parser (6.1.2 → 7.0.0) ·
[Repo](https://github.com/postcss/postcss-selector-parser) ·
[Changelog](https://github.com/postcss/postcss-selector-parser/blob/master/CHANGELOG.md)



<details>
<summary>Release Notes</summary>
<h4><a
href="https://github.com/postcss/postcss-selector-parser/releases/tag/v7.0.0">7.0.0</a></h4>

<blockquote><h1 dir="auto">7.0.0</h1>
<ul dir="auto">
<li>Feat: make insertions during iteration safe (major)</li>
</ul></blockquote>
<p><em>Does any of this look wrong? <a
href="https://depfu.com/packages/npm/postcss-selector-parser/feedback">Please
let us know.</a></em></p>
</details>

<details>
<summary>Commits</summary>
<p><a
href="1b1e9c3bc1...6158750aab">See
the full diff on Github</a>. The new version differs by 2 commits:</p>
<ul>
<li><a
href="6158750aab"><code>chore(release):
7.0.0</code></a></li>
<li><a
href="4fa6e860a1"><code>feat!:
make insertions during iteration safe (#295)</code></a></li>
</ul>
</details>












---
![Depfu
Status](https://depfu.com/badges/edd6acd35d74c8d41cbb540c30442adf/stats.svg)

[Depfu](https://depfu.com) will automatically keep this PR
conflict-free, as long as you don't add any commits to this branch
yourself. You can also trigger a rebase manually by commenting with
`@depfu rebase`.

<details><summary>All Depfu comment commands</summary>
<blockquote><dl>
<dt>@​depfu rebase</dt><dd>Rebases against your default branch and
redoes this update</dd>
<dt>@​depfu recreate</dt><dd>Recreates this PR, overwriting any edits
that you've made to it</dd>
<dt>@​depfu merge</dt><dd>Merges this PR once your tests are passing and
conflicts are resolved</dd>
<dt>@​depfu cancel merge</dt><dd>Cancels automatic merging of this
PR</dd>
<dt>@​depfu close</dt><dd>Closes this PR and deletes the branch</dd>
<dt>@​depfu reopen</dt><dd>Restores the branch and reopens this PR (if
it's closed)</dd>
<dt>@​depfu pause</dt><dd>Ignores all future updates for this dependency
and closes this PR</dd>
<dt>@​depfu pause [minor|major]</dt><dd>Ignores all future minor/major
updates for this dependency and closes this PR</dd>
<dt>@​depfu resume</dt><dd>Future versions of this dependency will
create PRs again (leaves this PR as is)</dd>
</dl></blockquote>
</details>

Co-authored-by: depfu[bot] <23717796+depfu[bot]@users.noreply.github.com>
2024-10-30 15:27:53 -04:00
Robin Malfait
94ea5e225b
Prepare v4.0.0-alpha.31 release (#14823)
Prepare v4.0.0-alpha.31 release
2024-10-30 07:53:51 -04:00
Robin Malfait
d68a780f98
Auto source detection improvements (#14820)
This PR introduces a new `source(…)` argument and improves on the
existing `@source`. The goal of this PR is to make the automatic source
detection configurable, let's dig in.

By default, we will perform automatic source detection starting at the
current working directory. Auto source detection will find plain text
files (no binaries, images, ...) and will ignore git-ignored files.

If you want to start from a different directory, you can use the new
`source(…)` next to the `@import "tailwindcss/utilities"
layer(utilities) source(…)`.

E.g.:

```css
/* ./src/styles/index.css */
@import 'tailwindcss/utilities' layer(utilities) source('../../');
```

Most people won't split their source files, and will just use the simple
`@import "tailwindcss";`, because of this reason, you can use
`source(…)` on the import as well:

E.g.:

```css
/* ./src/styles/index.css */
@import 'tailwindcss' source('../../');
```

Sometimes, you want to rely on auto source detection, but also want to
look in another directory for source files. In this case, yuo can use
the `@source` directive:

```css
/* ./src/index.css */
@import 'tailwindcss';

/* Look for `blade.php` files in `../resources/views` */
@source '../resources/views/**/*.blade.php';
```

However, you don't need to specify the extension, instead you can just
point the directory and all the same automatic source detection rules
will apply.

```css
/* ./src/index.css */
@import 'tailwindcss';

@source '../resources/views';
```

If, for whatever reason, you want to disable the default source
detection feature entirely, and only want to rely on very specific glob
patterns you define, then you can disable it via `source(none)`.

```css
/* Completely disable the default auto source detection */
@import 'tailwindcss' source(none);

/* Only look at .blade.php files, nothing else  */
@source "../resources/views/**/*.blade.php";
```

Note: even with `source(none)`, if your `@source` points to a directory,
then auto source detection will still be performed in that directory. If
you don't want that, then you can simply add explicit files in the globs
as seen in the previous example.

```css
/* Completely disable the default auto source detection */
@import 'tailwindcss' source(none);

/* Run auto source detection in `../resources/views` */
@source "../resources/views";
```

---------

Co-authored-by: Jordan Pittman <jordan@cryptica.me>
Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-10-29 20:33:34 +00:00
Robin Malfait
c439cdf43c
Internal refactor, introduce AtRule (#14802)
This PR introduces an internal refactor where we introduce the `AtRule`
CSS Node in our AST.

The motivation for this is that in a lot of places we need to
differentiate between a `Rule` and an `AtRule`. We often do this with
code that looks like this:

```ts
rule.selector[0] === '@' && rule.selector.startsWith('@media')
```

Another issue we have is that we often need to check for `'@media '`
including the space, because we don't want to match `@mediafoobar` if
somebody has this in their CSS. Alternatively, if you CSS is minified
then it could be that you have a rule that looks like
`@media(width>=100px)`, in this case we _also_ have to check for
`@media(`.

Here is a snippet of code that we have in our codebase:

```ts
// Find at-rules rules
if (node.kind === 'rule') {
  if (
    node.selector[0] === '@' &&
    (node.selector.startsWith('@media ') ||
      node.selector.startsWith('@media(') ||
      node.selector.startsWith('@custom-media ') ||
      node.selector.startsWith('@custom-media(') ||
      node.selector.startsWith('@container ') ||
      node.selector.startsWith('@container(') ||
      node.selector.startsWith('@supports ') ||
      node.selector.startsWith('@supports(')) &&
    node.selector.includes(THEME_FUNCTION_INVOCATION)
  ) {
    node.selector = substituteFunctionsInValue(node.selector, resolveThemeValue)
  }
}
```

Which will now be replaced with a much simpler version:
```ts
// Find at-rules rules
if (node.kind === 'at-rule') {
  if (
    (node.name === '@media' ||
      node.name === '@custom-media' ||
      node.name === '@container' ||
      node.name === '@supports') &&
    node.params.includes(THEME_FUNCTION_INVOCATION)
  ) {
    node.params = substituteFunctionsInValue(node.params, resolveThemeValue)
  }
}
```

Checking for all the cases from the first snippet is not the end of the
world, but it is error prone. It's easy to miss a case.

A direct comparison is also faster than comparing via the
`startsWith(…)` function.

---

Note: this is only a refactor without changing other code _unless_ it
was required to make the tests pass. The tests themselves are all
passing and none of them changed (because the behavior should be the
same).
The one exception is the tests where we check the parsed AST, which now
includes `at-rule` nodes instead of `rule` nodes when we have an
at-rule.
2024-10-29 01:17:25 +01:00
Robin Malfait
4e5e0a3e1b
Bump prettier-plugin-tailwindcss to latest version during upgrade (#14808)
This PR adds a migration to bump the `prettier-plugin-tailwindcss`
version to the latest version when upgrading your project. This is to
ensure that the plugin is compatible with the latest version of Tailwind
CSS.

Note: we will only do this _if_ you already used the
`prettier-plugin-tailwindcss` plugin in your project.
2024-10-28 23:46:24 +00:00
Jordan Pittman
10a8f1a725
Prepare v4.0.0-alpha.30 release (#14789) 2024-10-24 16:22:08 -04:00
Robin Malfait
f83041852d
Handle feedback from #14783 (#14788)
This PR is a continuation of #14783 to handle the feedback on that PR.

1. Update the test to be more realistic
2. Updated the comment

---------

Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-10-24 16:11:59 -04:00
Robin Malfait
430836f651
Ensure layer(…) on @import is only removed when @utility is present (#14783)
This PR fixes an issue where `layer(…)` next to imports were removed
where they shouldn't have been removed.

The issue exists if _any_ of the `@import` nodes in a file contains
`@utility`, if that's the case then we removed the `layer(…)` next to
_all_ `@import` nodes.

Before we were checking if the current sheet contained `@utility` or in
any of its children (sub-`@import` nodes).

This fixes that by looping over the `@import` nodes in the current
sheet, and looking for the `@utility` in the associated/imported file.
This way we update each node individually.

Test plan:
---

Added a dedicated integration test to make sure all codemods together
result in the correct result. Input:

96e8908378/integrations/upgrade/index.test.ts (L2076-L2108)

Output:

96e8908378/integrations/upgrade/index.test.ts (L2116-L2126)
2024-10-24 14:33:10 -04:00
Robin Malfait
5a1c2e7480
Only generate Preflight compatibility styles when Preflight is used (#14773)
This PR improves where we inject the border compatibility CSS. Before
this change we injected it if it was necessary in one of these spots:

- Above the first `@layer base` to group it together with existing
`@layer base` at-rules.
- If not present, after the last `@import`, to make sure that we emit
valid CSS because `@import` should be at the top (with a few
exceptions).

However, if you are working with multiple CSS files, then it could be
that we injected the border compatibility CSS multiple times if those
files met one of the above conditions.

To solve this, we now inject the border compatibility CSS with the same
rules as above, but we also have another condition:

The border compatibility CSS is only injected if the file also has a
`@import "tailwindcss";` _or_ `@import "tailwindcss/preflight";` in the
current file.

---

Added integration tests to make sure that we are generating what we
expect in a real environment. Some of the integration tests also use the
old `@tailwind` directives to make sure that the order of migrations is
correct (first migrate to `@import` syntax, then inject the border
compatibility CSS).

---------

Co-authored-by: Adam Wathan <adam.wathan@gmail.com>
2024-10-24 13:19:56 -04:00