5625 Commits

Author SHA1 Message Date
Robin Malfait
2abf228124
Minify arbitrary values when printing candidates (#14720)
This PR will optimize and simplify the candidates when printing the
candidate again after running codemods.

When we parse a candidate, we will add spaces around operators, for
example `p-[calc(1px+1px)]]` will internally be handled as `calc(1px +
1px)`. Before this change, we would re-print this as:
`p-[calc(1px_+_1px)]`.

This PR changes that by simplifying the candidate again so that the
output is `p-[calc(1px+1px)]`. In addition, if _you_ wrote
`p-[calc(1px_+_1px)]` then we will also simplify it to the concise form
`p-[calc(1px_+_1px)]`.


Some examples:

Input:
```html
<div class="[p]:flex"></div>
<div class="[&:is(p)]:flex"></div>
<div class="has-[p]:flex"></div>
<div class="px-[theme(spacing.4)-1px]"></div>
```

Output before:
```html
<div class="[&:is(p)]:flex"></div>
<div class="[&:is(p)]:flex"></div>
<div class="has-[&:is(p)]:flex"></div>
<div class="px-[var(--spacing-4)_-_1px]"></div>
```

Output after:
```html
<div class="[p]:flex"></div>
<div class="[p]:flex"></div>
<div class="has-[p]:flex"></div>
<div class="px-[var(--spacing-4)-1px]"></div>
```

---

This is alternative implementation to #14717 and #14718
Closes: #14717 
Closes: #14718
2024-10-18 22:44:25 +02:00
Robin Malfait
c4b97f6067
Migrate flex-grow -> grow and flex-shrink -> shrink (#14721)
This PR adds missing legacy migrations for migrating `flex-grow` to
`grow` and `flex-shrink` to `shrink`.

We already migrated `flex-grow-0` to `grow-0` and `flex-shrink-0` to
`shrink-0`, but forgot about these cases.
2024-10-18 17:58:01 +00:00
Robin Malfait
b7c4d25ae4
Ensure existing spaces in attribute selectors are valid (#14703)
This PR fixes an issue where spaces in a selector generated invalid CSS.

Lightning CSS will throw those incorrect lines of CSS out, but if you
are in an environment where Lightning CSS doesn't run then invalid CSS
is generated.

Given this input:

```html
data-[foo_=_"true"]:flex
```

This will be generated:

```css
.data-\[foo_\=_\"true\"\]\:flex[data-foo=""true] {
  display: flex;
}
```

With this PR in place, the generated CSS will now be:

```css
.data-\[foo_\=_\"true\"\]\:flex[data-foo="true"] {
  display: flex;
}
```

---------

Co-authored-by: Adam Wathan <adam.wathan@gmail.com>
2024-10-18 19:51:43 +02:00
Philipp Spiess
5c1bfd3a91
content rules from the JS config that are also covered by the automatic source detection should not be migrated to CSS (#14714)
This PR changes the migration of `content` rules in the JS config to CSS codemods.

When a `content` rule is processed which matches files that are _also matched by the automatic content discovery in v4_, we do not need to emit CSS for that rule. 

Take, for example this v3 configuration file:

```ts
import { type Config } from 'tailwindcss'

module.exports = {
  content: [
    './src/**/*.{html,js}', 
    './node_modules/my-external-lib/**/*.{html}'
  ],
} satisfies Config
```

Provided the base directories match up, the first rule will also be covered by the automatic content discovery in v4 and thus we only need to convert the second rule to CSS:

```css
@import "tailwindcss";
@source '../node_modules/my-external-lib/**/*.{html}';
```
2024-10-18 15:48:56 +02:00
Philipp Spiess
3da49f9837
Migrate static plugins with options to CSS (#14700)
This PR extends our JS configuration to CSS migration by also allowing `plugins` with options.  

An example of such config would be:

```js
import { type Config } from 'tailwindcss'
import myPlugin from "./myPlugin";

export default {
  plugins: [
    myPlugin({
      class: "tw",
    }),
  ],
} satisfies Config;
```

If the option object contains only values allowed in our CSS API, we can convert this to CSS entirely:

```css
@plugin './myPlugin' {
  class: 'tw';
}
```
2024-10-18 15:16:27 +02:00
Philipp Spiess
3e7695fb2c
Include simple config objects when extracting static plugins (#14699)
This PR updates the `extractStaticPlugins` function to also emit options as long as these are objects containing of only `string` and `number` values.

While doing this I also cleaned up the `require('custom-plugin')` detector to use a Tree-Sitter query instead of operating on the AST.

Here are the two cases we considered:

```js
import plugin1 from 'plugin1';

export default {
  plugins: [
    plugin1({
      foo: 'bar',
      num: 19,
    }),
    require('./plugin2')({
      foo: 'bar',
      num: 19,
    }),
  ]
}
```

The test plan also contains a number of scenarios that we do not want to migrate to CSS (because we do not have a CSS API we can use for e.g. nested objects). We do support all types that we also support in the CSS API.
2024-10-18 15:10:21 +02:00
Adam Wathan
b701ed6916
Prepare v4.0.0-alpha.28 release (#14709)
Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
v4.0.0-alpha.28
2024-10-17 17:03:28 -04:00
Philipp Spiess
0971eadd8f
Resolve theme keys when migrating JS config to CSS (#14675)
With the changes in #14672, it now becomes trivial to actually resolve
the config (while still retaining the reset behavior). This means that
we can now convert JS configs that use _functions_, e.g.:

```ts
import { type Config } from 'tailwindcss'

export default {
  theme: {
    extend: {
      colors: ({ colors }) => ({
        gray: colors.neutral,
      }),
    },
  },
} satisfies Config
```

This becomes:

```css
@import 'tailwindcss';

@theme {
  --color-gray-50: #fafafa;
  --color-gray-100: #f5f5f5;
  --color-gray-200: #e5e5e5;
  --color-gray-300: #d4d4d4;
  --color-gray-400: #a3a3a3;
  --color-gray-500: #737373;
  --color-gray-600: #525252;
  --color-gray-700: #404040;
  --color-gray-800: #262626;
  --color-gray-900: #171717;
  --color-gray-950: #0a0a0a;
}
```

---------

Co-authored-by: Adam Wathan <adam.wathan@gmail.com>
Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
2024-10-17 16:36:47 -04:00
Adam Wathan
edb066e0aa
Interpolate gradients using OKLCH by default (#14708)
This PR updates all of our gradient utilities to interpolate using OKLCH
by default instead of sRGB. This results in a smoother transition
between colors that preserves saturation throughout the gradient, rather
than hitting the dreaded dull gray zone in between your color stops.

Here are a few examples comparing sRGB (top) to OKLCH (bottom):

<img width="736" alt="image"
src="https://github.com/user-attachments/assets/57a158b6-a3a2-4eda-813e-1b596c7d4b3a">

We only apply a default interpolation mode when _not_ using arbitrary
values with the gradient utility.

Simplified but clear:

```css
.bg-linear-to-r {
  background-image: linear-gradient(to right in oklch, var(--gradient-color-stops));
}

.bg-linear-[to_right] {
  background-image: linear-gradient(to right, var(--gradient-color-stops));
}

.bg-linear-[to_right_in_hsl] {
  background-image: linear-gradient(to right in hsl, var(--gradient-color-stops));
}
```

---------

Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-10-17 16:16:14 -04:00
Adam Wathan
72c30d422a
Support linear gradient angles as bare values (#14707)
This PR adds support for linear gradient angles as bare values, like
this:

```
bg-linear-45 => linear-gradient(45deg, …)
```

We already support this for [conic
gradients](https://github.com/tailwindlabs/tailwindcss/pull/14467), so
this makes these utilities more consistent.

---------

Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-10-17 14:29:32 -04:00
Adam Wathan
feeb9f1b77
Remove invalid gradient fallbacks (#14705)
Prior to this PR we were providing fallback values for certain CSS
variables in our gradient utilities that just weren't necessary and
didn't do anything.

For example `bg-linear-to-r` was generating this:

```css
.bg-linear-to-r {
  --tw-gradient-position: to right;
  background-image: linear-gradient(
    var(--tw-gradient-stops, to right)
  );
}
```

…but `background-image: linear-gradient(to right)` is not valid CSS and
is thrown out by the browser.

This PR removes these fallback values entirely since there is nothing
sensible to fall back to anyways — you need to combine these utilities
with the `from-*`/`to-*` utilities or provide the complete gradient as
an arbitrary value for things to make sense.

---------

Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-10-17 13:48:58 -04:00
Robin Malfait
ec24b7af47
Add CODEOWNERS file (#14701)
This PR adds a new `CODEOWNERS` file so that the
`@tailwindlabs/engineering` will be automatically requested for review
when changes are made to the repository.
2024-10-17 09:05:44 -04:00
Robin Malfait
4a4be27dc1
Migrate theme(…) to var(…) in CSS (#14695)
This PR is a follow up from https://github.com/tailwindlabs/tailwindcss/pull/14664 migrates all the `theme(…)` calls in your CSS to `var(…)` if we can.

In at-rules, like `@media` we can't use `var(…)` so we have to use the modern version of `theme(…)`.

In declarations, we can convert to `var(…)` unless there is a modifier used in the `theme(…)` function, then we can only convert to the new `theme(…)` syntax without dot notation.

Input:
```css
@media theme(spacing.4) {
  .foo {
    background-color: theme(colors.red.900);
    color: theme(colors.red.900 / 75%); /* With spaces around the `/` */
    border-color: theme(colors.red.200/75%); /* Without spaces around the `/` */
  }
}
```

Output:
```css
@media theme(--spacing-4) {
/*     ^^^^^^^^^^^^^^^^^^     Use `theme(…)` since `var(…)` is invalid in this position*/
  .foo {
    background-color: var(--color-red-900); /* Converted to var(…) */
    color: theme(--color-red-900 / 75%); /* Convert to modern theme(…) */
    border-color: theme(--color-red-200 / 75%); /* Convert to modern theme(…) — pretty printed*/
  }
}
```
2024-10-17 11:50:27 +02:00
Robin Malfait
aff858a3e6
Make themeToVar reusable (#14694)
This PR makes the `themeToVar` code we already use for migrating the `theme(…)` calls to `var(…)` calls in the candidates (found in source files), reusable for the next PR where we want to migrate `theme(…)` calls in your actual CSS.

(This shouldn't really require a separate PR, but I'm playing with Graphite's stacked PR feature to see how it works in practice 😅)
2024-10-17 11:44:40 +02:00
Adam Wathan
2d45f5aa9a
Add first draft of new wide-gamut color palette (#14693)
This PR updates all of the colors in our default theme to use OKLCH
instead of RGB and increases the overall chroma to take advantage of the
wider color gamut.

Just a first draft based on @danhollick's initial work — expecting these
will be further refined before a stable release as we continue to test
them.

<img width="628" alt="image"
src="https://github.com/user-attachments/assets/2de1bfca-fddd-47f9-b609-39f26abdee41">

---------

Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-10-16 15:24:53 -04:00
Philipp Spiess
9b15a5c62e
Don't generate invalid CSS when migrating a complex screens config (#14691)
Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
2024-10-16 18:08:27 +02:00
depfu[bot]
5179fafdc3
Update eslint 8.57.0 → 9.11.1 (major) (#14547)
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?




#### ✳️ eslint (8.57.0 → 9.11.1) ·
[Repo](https://github.com/eslint/eslint) ·
[Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)



<details>
<summary>Release Notes</summary>
<p><em>Too many releases to show here. View the <a
href="https://github.com/eslint/eslint/blob/main/CHANGELOG.md">full
release notes</a>.</em></p>
</details>

<details>
<summary>Commits</summary>
<p><a
href="abea3b6f39...69e94597ca">See
the full diff on Github</a>. The new version differs by more commits
than we can show here.</p>
</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-16 14:45:07 +00:00
Robin Malfait
8dc343d9f6
Migrate theme(…) calls to var(…) or the modern theme(…) syntax (#14664)
This PR adds a codemod to convert `theme(…)` calls to `var(…)` calls. If
we can't safely do this, then we try to convert the `theme(…)` syntax
(dot notation) to the modern `theme(…)` syntax (with CSS variable-like
syntax).

### Let's look at some examples:

**Simple example:**

Input:
```html
<div class="bg-[theme(colors.red.500)]"></div>
```

Output:
```html
<div class="bg-[var(--color-red-500)]"></div>
```

---

**With fallback:**

Input:
```html
<div class="bg-[theme(colors.red.500,theme(colors.blue.500))]"></div>
```

Output:
```html
<div class="bg-[var(--color-red-500,var(--color-blue-500))]"></div>
```

---

**With modifiers:**

Input:
```html
<div class="bg-[theme(colors.red.500/75%)]"></div>
```

Output:
```html
<div class="bg-[var(--color-red-500)]/75"></div>
```

We can special case this, because if you are using that modifier syntax
we _assume_ it's being used in a `theme(…)` call referencing a color.
This means that we can also convert it to a modifier on the actual
candidate.

---

**With modifier, if a modifier is already present:**

Input:
```html
<div class="bg-[theme(colors.red.500/75%)]/50"></div>
```

Output:
```html
<div class="bg-[theme(--color-red-500/75%)]/50"></div>
```

In this case we can't use the `var(…)` syntax because that requires us
to move the opacity modifier to the candidate itself. In this case we
could use math to figure out the expected modifier, but that might be
too confusing. Instead, we convert to the modern `theme(…)` syntax.

---

**Multiple `theme(…)` calls with modifiers:**

Input:
```html
<div class="bg-[theme(colors.red.500/75%,theme(colors.blue.500/50%))]"></div>
```

Output:
```html
<div class="bg-[theme(--color-red-500/75%,theme(--color-blue-500/50%))]"></div>
```

In this case we can't convert to `var(…)` syntax because then we lose
the opacity modifier. We also can't move the opacity modifier to the
candidate itself e.g.: `/50` because we have 2 different variables to
worry about.

In this situation we convert to the modern `theme(…)` syntax itself.

---

**Inside variants:**

Input:
```html
<div class="max-[theme(spacing.20)]:flex"></div>
```

Output:
```html
<div class="max-[theme(--spacing-20)]:flex"></div>
```

Unfortunately we can't convert to `var(…)` syntax reliably because in
some cases (like the one above) the value will be used inside of an
`@media (…)` query and CSS doesn't support that at the time of writing
this PR.

So to be safe, we will not try to convert `theme(…)` to `var(…)` in
variants, but we will only upgrade the `theme(…)` call itself to modern
syntax.
2024-10-16 10:44:21 -04:00
Philipp Spiess
bf179916bf
Reset default @theme values for non extend JS theme config (#14672)
Imagine the following setup:

```css
/* src/input.css */
@import "tailwindcss";
@config "../tailwind.config.ts";
@theme {
  --color-red-500: #ef4444;
}
```

```ts
/* tailwind.config.ts */
export default {
  theme: {
    colors: {
      red: {
        600: '#dc2626'
      } 
    },
    extend: {
      colors: {
        400: '#f87171'
      }
    }
  }
}
```

Since the theme object in the JS config contains `colors` in the
non-`extends` block, you would expect this to _not pull in all the
default colors imported via `@import "tailwindcss";`_. This, however,
wasn't the case right now since all theme options were purely _additive_
to the CSS.

This PR makes it so that non-`extend` theme keys _overwrite default CSS
theme values_. The emphasis is on `default` here since you still want to
be able to overwrite your options via `@theme {}` in user space.

This now generates the same CSS that our upgrade codemods would also
generate as this would apply the new CSS right after the `@import
"tailwindcss";` rule resulting in:

```css
@import "tailwindcss";
@theme {
  --color-*: initial;
  --color-red-400: #f87171;
  --color-red-600: #dc2626;
}
@theme {
  --color-red-500: #ef4444;
}
```

## Keyframes

This PR also adds a new core API to unset keyframes the same way. We
previously had no option of doing that but while working on the above
codemods we noticed that keyframes should behave the same way:

```css
@import "tailwindcss";
@theme {
  --keyframes-*: initial;
  @keyframes spin {
    to {
      transform: rotate(361deg);
    }
  }
}
```

To do this, the keyframes bookeeping was moved from the main Tailwind
CSS v4 file into the `Theme` class.


_I’m not sure super of the API yet but we would need a way for the
codemods to behave the same as out interop layer here. Option B is that
we don't reset keyframes the same way we reset other theme variables_.
2024-10-16 16:06:09 +02:00
Robin Malfait
0e262a13e6
@apply is not allowed inside @keyframes (#14687)
This PR makes sure that you cannot use `@apply` inside `@keyframes`. 

While some utilities can be used in `@keyframes`, the moment you
introduce a variant, that's not going to work anymore because they need
to operate on selectors which `@keyframes` don't have.

This PR now removes all usages of `@apply` in `@keyframes`.
2024-10-16 13:55:14 +02:00
Robin Malfait
4395aac729
Add missing changelog entry (#14686)
<!--

👋 Hey, thanks for your interest in contributing to Tailwind!

**Please ask first before starting work on any significant new
features.**

It's never a fun experience to have your pull request declined after
investing a lot of time and effort into a new feature. To avoid this
from happening, we request that contributors create an issue to first
discuss any significant new features. This includes things like adding
new utilities, creating new at-rules, or adding new component examples
to the documentation.


https://github.com/tailwindcss/tailwindcss/blob/master/.github/CONTRIBUTING.md

-->
2024-10-16 13:25:53 +02:00
Jordan Pittman
92a43d6904
Speed up template migrations (#14679)
This PR does two things:
- Computes UTF-16 string positions in Rust rather than in JS —
eliminating a significant number of traversals of the input string
- Applies replacements to the content in ascending order so we only ever
move forward through the source string — this lets v8 optimize string
concatenation
2024-10-16 13:13:48 +02:00
Philipp Spiess
be6c69e29f
Remove .gitattributes file (#14676)
I added the `.gitattributes` a while back because I thought it would
help us make it simpler when rebasing changes to the `CHANGELOG.md`
file. However, I don't think this is actually true. Now, instead of a
merge conflict, the rebase just ends up duplicating a lot of lines which
we only see when we review the PR on GitHub later which is really
annoying.

So, for now, let's remove it again. Ideally we can have a better merge
strategy here (or potentially other tools).
2024-10-15 17:47:24 +02:00
depfu[bot]
e2109a3b92
Update @playwright/test 1.47.1 → 1.48.0 (minor) (#14673)
Here is everything you need to know about this update. Please take a
good look at what changed and the test results before merging this pull
request.

### What changed?




#### ✳️ @​playwright/test (1.47.1 → 1.48.0) ·
[Repo](https://github.com/Microsoft/playwright)



<details>
<summary>Release Notes</summary>
<h4><a
href="https://github.com/microsoft/playwright/releases/tag/v1.48.0">1.48.0</a></h4>

<blockquote><h2 dir="auto">WebSocket routing</h2>
<p dir="auto">New methods <a
href="https://playwright.dev/docs/api/class-page#page-route-web-socket">page.routeWebSocket()</a>
and <a
href="https://playwright.dev/docs/api/class-browsercontext#browser-context-route-web-socket">browserContext.routeWebSocket()</a>
allow to intercept, modify and mock WebSocket connections initiated in
the page. Below is a simple example that mocks WebSocket communication
by responding to a <code class="notranslate">"request"</code> with a
<code class="notranslate">"response"</code>.</p>
<div class="highlight highlight-source-js" dir="auto"><pre
class="notranslate"><span class="pl-k">await</span> <span
class="pl-s1">page</span><span class="pl-kos">.</span><span
class="pl-en">routeWebSocket</span><span class="pl-kos">(</span><span
class="pl-s">'/ws'</span><span class="pl-kos">,</span> <span
class="pl-s1">ws</span> <span class="pl-c1">=&gt;</span> <span
class="pl-kos">{</span>
<span class="pl-s1">ws</span><span class="pl-kos">.</span><span
class="pl-en">onMessage</span><span class="pl-kos">(</span><span
class="pl-s1">message</span> <span class="pl-c1">=&gt;</span> <span
class="pl-kos">{</span>
<span class="pl-k">if</span> <span class="pl-kos">(</span><span
class="pl-s1">message</span> <span class="pl-c1">===</span> <span
class="pl-s">'request'</span><span class="pl-kos">)</span>
<span class="pl-s1">ws</span><span class="pl-kos">.</span><span
class="pl-en">send</span><span class="pl-kos">(</span><span
class="pl-s">'response'</span><span class="pl-kos">)</span><span
class="pl-kos">;</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span
class="pl-kos">;</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span
class="pl-kos">;</span></pre></div>
<p dir="auto">See <a
href="https://playwright.dev/docs/api/class-websocketroute">WebSocketRoute</a>
for more details.</p>
<h2 dir="auto">UI updates</h2>
<ul dir="auto">
<li>New "copy" buttons for annotations and test location in the HTML
report.</li>
<li>Route method calls like <a
href="https://playwright.dev/docs/api/class-route#route-fulfill">route.fulfill()</a>
are not shown in the report and trace viewer anymore. You can see which
network requests were routed in the network tab instead.</li>
<li>New "Copy as cURL" and "Copy as fetch" buttons for requests in the
network tab.</li>
</ul>
<h2 dir="auto">Miscellaneous</h2>
<ul dir="auto">
<li>Option <a
href="https://playwright.dev/docs/api/class-apirequestcontext#api-request-context-fetch-option-form"><code
class="notranslate">form</code></a> and similar ones now accept <a
href="https://playwright.dev/docs/api/class-formdata">FormData</a>.</li>
<li>New method <a
href="https://playwright.dev/docs/api/class-page#page-request-gc">page.requestGC()</a>
may help detect memory leaks.</li>
<li>New option <a
href="https://playwright.dev/docs/api/class-test#test-step-option-location"><code
class="notranslate">location</code></a> to pass custom step
location.</li>
<li>Requests made by <a
href="https://playwright.dev/docs/api/class-apirequestcontext">APIRequestContext</a>
now record detailed timing and security information in the HAR.</li>
</ul>
<h2 dir="auto">Browser Versions</h2>
<ul dir="auto">
<li>Chromium 130.0.6723.19</li>
<li>Mozilla Firefox 130.0</li>
<li>WebKit 18.0</li>
</ul>
<p dir="auto">This version was also tested against the following stable
channels:</p>
<ul dir="auto">
<li>Google Chrome 129</li>
<li>Microsoft Edge 129</li>
</ul></blockquote>
<h4><a
href="https://github.com/microsoft/playwright/releases/tag/v1.47.2">1.47.2</a></h4>

<blockquote><h3 dir="auto">Highlights</h3>
<p dir="auto"><a
href="https://bounce.depfu.com/github.com/microsoft/playwright/pull/32699">#32699</a>
[REGRESSION]: fix(codegen): use content_frame property in
python/.NET<br>
<a
href="https://bounce.depfu.com/github.com/microsoft/playwright/issues/32706">#32706</a>
[REGRESSION]: page.pause() does not pause test timeout after 1.47<br>
<a
href="https://bounce.depfu.com/github.com/microsoft/playwright/pull/32661">#32661</a>
- fix(trace-viewer): time delta between local and remote actions</p>
<h2 dir="auto">Browser Versions</h2>
<ul dir="auto">
<li>Chromium 129.0.6668.29</li>
<li>Mozilla Firefox 130.0</li>
<li>WebKit 18.0</li>
</ul>
<p dir="auto">This version was also tested against the following stable
channels:</p>
<ul dir="auto">
<li>Google Chrome 128</li>
<li>Microsoft Edge 128</li>
</ul></blockquote>
<p><em>Does any of this look wrong? <a
href="https://depfu.com/packages/npm/@playwright%2Ftest/feedback">Please
let us know.</a></em></p>
</details>

<details>
<summary>Commits</summary>
<p><a
href="3d2ffd0fe9...0cdbb11068">See
the full diff on Github</a>. The new version differs by more commits
than we can show here.</p>
</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-15 17:36:05 +02:00
Philipp Spiess
a75152d162
Release v4.0.0-alpha.27 (#14671) v4.0.0-alpha.27 2024-10-15 10:28:34 +00:00
Robin Malfait
2b13547a0d
Migrate arbitrary values to bare values (#14669)
This PR adds a codemod that can convert arbitrary values to the cleaner
bare values if we can.

For example, some classes use arbitrary values such as `col-start-[16]`,
but in v4 we have bare values for some plugins that don't really need to
adhere to your design system.

In this case, we can convert `col-start-[16]` to just `col-start-16`.

Another use case is for utilities that use fractions. For example the
`aspect-*` plugin.

A custom aspect ratio such as `aspect-[16/9]` can be converted to
`aspect-16/9`.

There are some rules attached to this migration:

1. We can only migrate arbitrary values that is a single positive
integer, or an arbitrary value that is a fraction where the numerator
and denominator are both positive integers.
2. We make sure that some CSS can be generated once its converted to a
bare value.
2024-10-15 09:45:03 +00:00
Robin Malfait
36acad0306
Ensure font-stretch utilities only accepts positive integer bare values (#14670)
This PR fixes an issue where bare values in the `font-stretch` utility
such as `font-stretch-50.5%` compiled. But for bare values, we want
these values to be positive integers only so that we don't have too many
special characters.

If you want to use `50.5%`, you can still use `font-stretch-[50.5%]` as
a utility.
2024-10-15 09:39:05 +00:00
Philipp Spiess
782bc26135
Migrate keyframes from JS to CSS (#14666)
This PR adds support for rewriting JS theme config `keyframes` to CSS as
part of the JS config to CSS migration.

Example:

```ts
import { type Config } from 'tailwindcss'

module.exports = {
  theme: {
    extend: {
      keyframes: {
        'spin-clockwise': {
          '0%': { transform: 'rotate(0deg)' },
          '100%': { transform: 'rotate(360deg)' },
        },
        'spin-counterclockwise': {
          '0%': { transform: 'rotate(0deg)' },
          '100%': { transform: 'rotate(-360deg)' },
        },
      },
      animation: {
        'spin-clockwise': 'spin-clockwise 1s linear infinite',
        'spin-counterclockwise': 'spin-counterclockwise 1s linear infinite',
      },
    },
  },
} satisfies Config
```

Will be printed as:

```css
@theme {
  --animate-spin-clockwise: spin-clockwise 1s linear infinite;
  --animate-spin-counterclockwise: spin-counterclockwise 1s linear infinite;

  @keyframes spin-clockwise {
    0% {
      transform: rotate(0deg);
    }
    100% {
      transform: rotate(360deg);
    }
  }
  @keyframes spin-counterclockwise {
    0% {
      transform: rotate(0deg);
    }
    100% {
      transform: rotate(-360deg);
    }
  }
}
```
2024-10-15 11:21:19 +02:00
Philipp Spiess
468cb5e99e
Detect and migrate static plugin usages (#14648)
This PR builds on top of the new [JS config to CSS
migration](https://github.com/tailwindlabs/tailwindcss/pull/14651) and
extends it to support migrating _static_ plugins.

What are _static_ plugins you might ask? Static plugins are plugins
where we can statically determine that these are coming from a different
file (so there is nothing inside the JS config that creates them). An
example for this is this config file:

```js
import typographyPlugin from '@tailwindcss/typography'
import { type Config } from 'tailwindcss'

export default {
  content: ['./src/**/*.{js,jsx,ts,tsx}'],
  darkMode: 'selector',
  plugins: [typographyPlugin],
} satisfies Config
```

Here, the `plugins` array only has one element and it is a static import
from the `@tailwindcss/typography` module. In this PR we attempt to
parse the config file via Tree-sitter to extract the following
information from this file:

- What are the contents of the `plugins` array
- What are statically imported resources from the file

We then check if _all_ entries in the `plugins` array are either static
resources or _strings_ (something I saw working in some tests but I’m
not sure it still does). We migrate the JS config file to CSS if all
plugins are static and we can migrate them to CSS `@plugin` calls.

## Todo

This will need to be rebased after the updated tests in #14648
2024-10-14 17:45:36 +02:00
Philipp Spiess
4b19de3a45
Address follow-up work for #14639 (#14650)
This PR adds a few more test cases to #14639 and updates the
documentation.

---------

Co-authored-by: Jordan Pittman <jordan@cryptica.me>
2024-10-14 14:33:14 +00:00
Philipp Spiess
4e219dc97d
Revert "Warn on use of plugin parameters as function" (#14662)
Reverts tailwindlabs/tailwindcss#14661
2024-10-14 09:46:12 -04:00
Robin Malfait
f2ebb8eb82
Fix var(…) as the opacity value inside the theme(…) function (#14653)
Inside the `theme(…)` function, we can use the `/` character for
applying an opacity. For example `theme(colors.red.500 / 50%)` will
apply a 50% opacity to the `colors.red.500` value.

However, if you used a variable instead of the hardcoded `50%` value,
then this was not parsed correctly. E.g.: `theme(colors.red.500 /
var(--opacity))`

_If_ we have this exact syntax (with the spaces), then it parses, but
some information is lost:

```html
<div class="bg-[theme(colors.red.500_/_var(--opacity))]"></div>
```

Results in:
```css
.bg-\[theme\(colors\.red\.500_\/_var\(--opacity\)\)\] {
  background-color: color-mix(in srgb, #ef4444 calc(var * 100%), transparent);
}
```
Notice that the `var(--opacity)` is just parsed as `var`, and the
`--opacity` is lost.

Additionally, if we drop the spaces, then it doesn't parse at all:

```html
<div class="bg-[theme(colors.red.500/var(--opacity))]"></div>
```

Results in:
```css
```

This means that we have to handle 2 issues to make this work:
1. We have to properly handle the `/` character as a proper separator.
2. If we have sub-functions, we have to make sure to print them in full
(instead of only the very first node (`var` in this case)).
2024-10-14 12:08:41 +00:00
Philipp Spiess
a64e209888
Warn on use of plugin parameters as function (#14661)
Quick follow-up to #14659 base don @thecrypticace's idea:

- This behavior is no longer added to the types of the Plugin API to be
consistent with v3
- When the plugin argument is used as a function, we now warn the first
time
2024-10-14 13:57:02 +02:00
Philipp Spiess
99f2127b7d
Callback in theme properties is also the theme function (#14659)
Something we noticed while testing the codemods on one of our codebases
is that the callback passed to the `theme` function properties doesn't
only expose some properties like `colors`, but it's also a function
itself.

```ts
/** @type {import('tailwindcss').Config} */
export default {
  theme: {
    extend: {
      colors: (theme) => {
        // The `theme` is a theme function _and_ the object...
        console.log(theme('spacing.2'), theme.colors.red['500'])
        return {}
      },
    },
  },
  plugins: [],
}
```

E.g.: https://play.tailwindcss.com/eV7Jgv17X1?file=config

---
h/t to @RobinMalfait for the issue description
2024-10-14 10:29:12 +00:00
Philipp Spiess
c009c9c38b
Support the color property in JS theme configuration callbacks (#14651)
While working on some fixes for #14639 I noticed that the following v3
configuration file would not load properly in v4:

```ts
import { type Config } from 'tailwindcss'

export default {
  content: ['./src/**/*.{js,jsx,ts,tsx}'],
  theme: {
    extend: {
      colors: ({ colors }) => ({
        gray: colors.neutral,
      }),
  },
} satisfies Config
```

The reason for this is that we did not pass the `colors` property to the
callback function. Since we have colors available now, we can easily add
it.

---------

Co-authored-by: Adam Wathan <adam.wathan@gmail.com>
2024-10-11 18:07:59 +02:00
Robin Malfait
e6d3fa0cc4
Migrate aria-*, data-* and supports-* variants from arbitrary values to bare values (#14644)
This PR adds a new codemod that can migrate `data-*` and `aria-*`
variants using arbitrary values to bare values.

In Tailwind CSS v3, if you want to conditionally apply a class using
data attributes, then you can write `data-[selected]:flex`. This
requires the DOM element to have a `data-selected=""` attribute. In
Tailwind CSS v4 we can simplify this, by dropping the brackets and by
using `data-selected:flex` directly.

This migration operates on the internal AST, which means that this also
just works for compound variants such as
`group-has-data-[selected]:flex` (which turns into
`group-has-data-selected:flex`).

Additionally, this codemod is also applicable to `aria-*` variants. The
biggest difference is that in v4 `aria-selected` maps to an attribute of
`aria-selected="true"`. This means that we can only migrate
`aria=[selected="true"]:flex` to `aria-selected:flex`.

Last but not least, we also migrate `supports-[gap]` to `supports-gap`
if the passed in value looks like a property. If not, e.g.:
`supports-[display:grid]` then it stays as-is.
2024-10-11 10:41:37 -04:00
Adam Wathan
7c7acace5c
Tweak changelog entries (#14649) 2024-10-11 10:38:46 -04:00
Jordan Pittman
d9fe39c30a
Convert to/from v3 theme keys in configs and plugins (#14642)
A few theme keys have changed in v4 relative to v3:
- `screens` -> `--breakpoint-*`
- `colors` -> `--color-*`
- `animation` -> `--animate-*`
- `borderRadius` -> `--radius-*`
- `boxShadow` -> `--shadow-*`

When using the `theme()` function we wouldn't pick up values from the
CSS for some of these. Likewise, when loading a v3 config not all of
these would be pushed back into the CSS theme and they should've been.

This PR addresses both of these problems.
2024-10-11 10:24:53 -04:00
Robin Malfait
88b52b66e5
update CHANGELOG 2024-10-11 15:56:12 +02:00
Adam Wathan
5a2938dbfc
Update CHANGELOG.md 2024-10-11 09:50:53 -04:00
Philipp Spiess
0cfb98484b
Add simple JS config migration (#14639)
This PR implements the first version of JS config file migration to CSS.
It is based on the most simple config setups we are using in the
Tailwind UI templates Commit, Primer, Radiant, and Studio.

The example we use in the integration test is a config that looks like
this:

```js
import { type Config } from 'tailwindcss'
import defaultTheme from 'tailwindcss/defaultTheme'

module.exports = {
  darkMode: 'selector',
  content: ['./src/**/*.{html,js}'],
  theme: {
    boxShadow: {
      sm: '0 2px 6px rgb(15 23 42 / 0.08)',
    },
    colors: {
      red: {
        500: '#ef4444',
      },
    },
    fontSize: {
      xs: ['0.75rem', { lineHeight: '1rem' }],
      sm: ['0.875rem', { lineHeight: '1.5rem' }],
      base: ['1rem', { lineHeight: '2rem' }],
    },
    extend: {
      colors: {
        red: {
          600: '#dc2626',
        },
      },
      fontFamily: {
        sans: 'Inter, system-ui, sans-serif',
        display: ['Cabinet Grotesk', ...defaultTheme.fontFamily.sans],
      },
      borderRadius: {
        '4xl': '2rem',
      },
    },
  },
  plugins: [],
} satisfies Config
```

As you can see, this file only has a `darkMode` selector, custom
`content` globs, a `theme` (with some theme keys being overwriting the
default theme and some others extending the defaults). Note that it does
not support `plugins` and/or `presets` yet.

In the case above, we will find the CSS file containing the existing
`@tailwind` directives and are migrating it to the following:

```css
@import 'tailwindcss';

@source './**/*.{html,js}';

@variant dark (&:where(.dark, .dark *));

@theme {
  --box-shadow-*: initial;
  --box-shadow-sm: 0 2px 6px rgb(15 23 42 / 0.08);

  --color-*: initial;
  --color-red-500: #ef4444;

  --font-size-*: initial;
  --font-size-xs: 0.75rem;
  --font-size-xs--line-height: 1rem;
  --font-size-sm: 0.875rem;
  --font-size-sm--line-height: 1.5rem;
  --font-size-base: 1rem;
  --font-size-base--line-height: 2rem;

  --color-red-600: #dc2626;

  --font-family-sans: Inter, system-ui, sans-serif;
  --font-family-display: Cabinet Grotesk, ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";

  --border-radius-4xl: 2rem;
} 
```

This replicates all features of the JS config so we can even delete the
existing JS config in this case.

---------

Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
2024-10-11 15:27:53 +02:00
Robin Malfait
bd3d6bc09b
Migrate legacy classes to the v4 alternative (#14643)
This PR adds a mapping from legacy classes to new classes. For example,
the `flex-shrink-0` is still used in our projects, but is deprecated in
v3.

The migration does a tiny bit of parsing because we can't rely on
`designSystem.parseCandidate(…)` because this requires the utility to be
defined which is not the case for legacy classes.

This migration runs _after_ the migration where we handle prefixes, so
we don't have to worry about that. We do have to worry about the `!`
location, because the `important` migration also relies on the
`designSystem`.

| Old                 | New                    |
| ------------------- | ---------------------- |
| `overflow-clip`     | `text-clip`            |
| `overflow-ellipsis` | `text-ellipsis`        |
| `flex-grow-0`       | `grow-0`               |
| `flex-shrink-0`     | `shrink-0`             |
| `decoration-clone`  | `box-decoration-clone` |
| `decoration-slice`  | `box-decoration-slice` |
2024-10-11 14:22:55 +02:00
depfu[bot]
f0b65e360c
Update turbo 2.1.2 → 2.1.3 (patch) (#14646)
Here is everything you need to know about this update. Please take a
good look at what changed and the test results before merging this pull
request.

### What changed?




#### ✳️ turbo (2.1.2 → 2.1.3) ·
[Repo](https://github.com/turborepo/turbo)





Sorry, we couldn't find anything useful about this release.











---
![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-11 12:50:15 +02:00
Robin Malfait
a3812942ac
Use consistent quotes (#14640)
Small improvement, we noticed that some quotes were not consistent with
others. Let's make them consistent!
2024-10-10 14:29:36 +00:00
Robin Malfait
fb1731a2de
Inject @config "..." when a tailwind.config.{js,ts,...} is detected (#14635)
This PR injects a `@config "…"` in the CSS file if a JS based config has
been found.

We will try to inject the `@config` in a sensible place:
1. Above the very first `@theme`
2. If that doesn't work, below the last `@import`
3. If that doesn't work, at the top of the file (as a last resort)
2024-10-10 14:02:42 +00:00
Jordan Pittman
4d1becd2f9
Migrate utilities in CSS files imported into layers (#14617)
When a stylesheet is imported with `@import “…” layer(utilities)` that
means that all classes in that stylesheet and any of its imported
stylesheets become candidates for `@utility` conversion.

Doing this correctly requires us to place `@utility` rules into separate
stylesheets (usually) and replicate the import tree without layers as
`@utility` MUST be root-level. If a file consists of only utilities we
won't create a separate file for it and instead place the `@utility`
rules in the same stylesheet.

Been doing a LOT of pairing with @RobinMalfait on this one but I think
this is finally ready to be looked at

---------

Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
2024-10-10 15:44:04 +02:00
Philipp Spiess
75b906643c
Migrate simple PostCSS setup (#14612)
This PR attempts to detect simple postcss setups: These are setups that
do not load dynamic modules and are based off the examples we are
[recommending in our
docs](https://tailwindcss.com/docs/installation/using-postcss). We
detect wether a config is appropriate by having it use the object plugin
config and by not requiring any other modules:

```js
module.exports = {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  },
}
```

When we find such a config file, we will go over it line-by-line and
attempt to:

- Upgrade `tailwindcss:` to `'@tailwindcss/postcss':`
- Remove `autoprefixer` if used

We then attempt to install and remove the respective npm packages based
on the package manger we detect.

And since we now have logic to upgrade packages, this also makes sure to
install `tailwindcss@next` at the end of a sucessful migration.

---------

Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
2024-10-10 15:09:14 +02:00
Robin Malfait
3ae22f1f9d
Migrate @media screen(…) (#14603)
This PR adds a codemod that migrates the `@media screen(…)` to the
properly expanded `@media (…)` syntax.

```css
@media screen(md) {
  .foo {
    color: red;
  }
}
```

Will be converted to:
```css
@media (width >= 48rem) {
  .foo {
    color: red;
  }
}
```

If you happen to have custom screens (even complex ones), the screen
will be converted to a custom media query.

```css
@media screen(foo) {
  .foo {
    color: red;
  }
}
```
With a custom `tailwind.config.js` file with a config like this:
```js
module.exports = {
  // …
  theme: {
    screens: {
      foo: { min: '100px', max: '123px' },
    },
  }
}
```

Then the codemod will convert it to:
```css
@media (123px >= width >= 100px) {
  .foo {
    color: red;
  }
}
```
2024-10-10 15:06:53 +02:00
Jordan Pittman
958bfc9d89
Pass options when using addComponents and matchComponents (#14590)
We forgot to pass `options` from `addComponents` to `addUtilities` and
from `matchComponents` to `matchUtilities`.

This didn't affect anything using addComponents but anything that used
`matchComponents` wouldn't have worked 😬
2024-10-10 12:56:59 +00:00
Jordan Pittman
a6231b78c1
Ensure auto complete suggestions work when using matchUtilities (#14589)
Discovered `matchUtilities(…)` wasn't populating intellisense on v4 when
working on Tailwind Play earlier today. This PR fixes this so plugins
using matchUtilities also have intellisense suggestions.
2024-10-10 14:51:52 +02:00