This PR bumps Lightning CSS. The `node/index.js` file in the package
changed, so we had to update the patched version of it as well.
We also had to update the patches for `@parcel/watcher` and
`lightningcss` now that they ship with `detect-libc@2`. Unfortunately,
we still require the patches because we also need to take the
`process.env.PLATFORM_LIBC` into account. Another issue is that bun
needs to be able to statically analyze the `require(…)` calls, so using
the nice `parts.push` approach doesn't really work here.
# Test plan
1. Existing tests should pass
2. Updated some tests to reflect the changes in the generated CSS based
on the version bump.
[ci-all]
This PR fixes a bug in the canonicalization process where if a few
utilities collapse into a smaller one, and the smaller one is part of
the original list, then it results in an empty list.
It will be more clear with an example. Let's say you have this setup:
```
w-[calc(1rem+0.25rem)] h-[calc(1rem+0.25rem)] size-5
```
The first step is that this will result in:
```
w-5 h-5 size-5
```
Then the `w-5 h-5` can turn into `size-5`. But the existing `size-5`,
can also be replaced by the `size-5`.
Internally, when we have a replacement, then we mark all the classes
that can be replaced as "droppable", so they would be dropped from the
list. But in this scenario we also marked `size-5` as droppable,
resulting in an empty list.
If an additional class existed:
```
w-[calc(1rem+0.25rem)] h-[calc(1rem+0.25rem)] size-5 flex
```
The result would be
```
flex
```
Instead of the expected:
```
size-5 flex
```
## Test plan
1. Existing tests pass
2. Added new tests with and without an additional class
This PR adds support for canonicalization of utilities that accept bare
values and exceed the default spacing scale we use for intellisense.
Right now, all utilities are behind functions, so the only way to know
whether something compiles is by compiling a candidate, e.g. `w-8` and
passing it to the utility functions. To help us, we use the intellisense
APIs that we use for suggestions.
Most utilities that accept bare values, have suggestions up until
`*-96`, so `w-96 h-96` would be canonicalized to `size-96`. But the
moment we exceed that, the result stays as-is.
```
→ w-96 h-96
= size-96
→ w-1234 h-1234
= h-1234 w-1234
```
This PR ensures that the last scenario also gets canonicalized to
`size-1234` instead of staying as `h-1234 w-1234`.
```
→ w-96 h-96
= size-96
→ w-1234 h-1234
= size-1234
```
## Test plan
1. Existing tests pass
2. Added new tests for utilities with bare values
[ci-all] just to see if this additional logic doesn't cause timeouts in
CI for WIndows. In my testing this doesn't have a significant impact on
performance at all.
## Summary
- Adds `--stream` flag to `tailwindcss canonicalize` that reads
candidate groups from stdin line by line and writes canonicalized
results to stdout
- Keeps the design system loaded across requests, making it suitable as
a long-running sidecar process
- Empty lines pass through, keeping request/response pairs aligned
## Motivation
Non-JS tools (formatters, editor plugins, etc.) currently have no
lightweight way to canonicalize Tailwind classes. The existing batch
mode works for one-off use, but tools that need to canonicalize
repeatedly pay the cost of loading the design system each time.
With `--stream`, a tool can start `tailwindcss canonicalize --stream`
once and send candidate groups over stdin as needed:
```sh
$ echo -e "py-3 p-1 px-3\nmt-2 mr-2 mb-2 ml-2" | tailwindcss canonicalize --stream
p-3
m-2
```
Related discussion:
https://github.com/tailwindlabs/tailwindcss/discussions/19736
---------
Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
Removes unused braces and @types/braces from @tailwindcss/upgrade
package.json as reported in issue #19794
---------
Co-authored-by: CG1AI <sidwu@CG1AIdeMac-mini.local>
Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
This PR does some generic cleanup to the codebase.
I'm playing with oxfmt and oxlint and noticed some unnecessary escapes.
Might add these dependencies to the project later (and rolldown for
building). But baby steps for now.
## Test plan
1. All tests should still pass
This PR adds support for Vite 8 when using the `@tailwindcss/vite`
package.
From the package's perspective, not a lot had to change, just the `vite`
peer dependency now has an additional `^8.0.0` version range.
Closes: #19789
## Test plan
1. Existing tests pass
2. Manually tested in the `./playgrounds/vite` playground
3. Added Vite 8 integration tests to verify that the plugin works with
Vite 8
<!--
👋 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 a discussion to
first discuss any significant new features.
For more info, check out the contributing guide:
https://github.com/tailwindlabs/tailwindcss/blob/main/.github/CONTRIBUTING.md
-->
## Summary
- Closes https://github.com/tailwindlabs/tailwindcss/issues/19744
- Closes https://github.com/vitejs/vite-plugin-react/issues/1118
- Closes https://github.com/wakujs/waku/issues/1963
The change in https://github.com/tailwindlabs/tailwindcss/pull/19670
didn't take account for server only modules managed by SSR framework.
Forcing full reload for this path breaks server HMR. This PR added a
check to determine whether the same modified file has associated modules
in a different environment module graph to avoid this.
## Test plan
<!--
Explain how you tested your changes. Include the exact commands that you
used to verify the change works and include screenshots/screen
recordings of the update behavior in the browser if applicable.
-->
Added an integration test for React router HDR (server loader hmr). This
test fails on main.
Also the local build is tested on `@vitejs/plugin-rsc` CI and confirmed
the fix https://github.com/vitejs/vite-plugin-react/pull/1132
---------
Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
This PR fixes an internal source map warning when running tests. To
solve this, we encode the `=` as `\x3d` instead. I'm not 100% sure if
Vitest was hanging on this but it solved the following warning:
```
✓ @tailwindcss/cli src/utils/format-ns.test.ts (21 tests) 3ms
11:43:59 AM [vite] (ssr) Failed to load source map for /Users/robin/github.com/tailwindlabs/tailwindcss/packages/@tailwindcss-node/dist/index.mjs.
Error: An error occurred while trying to read the map file at ${i}
Error: ENOENT: no such file or directory, open '/Users/robin/github.com/tailwindlabs/tailwindcss/packages/@tailwindcss-node/dist/${i}'
at open (node:internal/fs/promises:634:25)
at Object.readFile (node:internal/fs/promises:1238:14)
at extractSourcemapFromFile (file:///Users/robin/github.com/tailwindlabs/tailwindcss/node_modules/.pnpm/vite@7.0.0_@types+node@20.19.1_jiti@2.6.1_lightningcss@1.31.1_patch_hash=tzyxy3asfxcqc7ihroou_7epcep7uhfc7zidzdmxzgvdzwi/node_modules/vite/dist/node/chunks/dep-Bsx9IwL8.js:8349:65)
at loadAndTransform (file:///Users/robin/github.com/tailwindlabs/tailwindcss/node_modules/.pnpm/vite@7.0.0_@types+node@20.19.1_jiti@2.6.1_lightningcss@1.31.1_patch_hash=tzyxy3asfxcqc7ihroou_7epcep7uhfc7zidzdmxzgvdzwi/node_modules/vite/dist/node/chunks/dep-Bsx9IwL8.js:26405:22)
```
## Test plan
1. Existing tests pass
2. Added a failing test to ensure that the source maps are emitted
correctly
## Problem
`canonicalizeCandidates` crashes when called with `collapse: true` and
the candidate list includes utilities whose CSS output contains no
standard declaration properties (only `@property` rules and CSS custom
properties).
This is reproducible with vanilla Tailwind CSS and no custom
configuration:
```js
designSystem.canonicalizeCandidates(['shadow-sm', 'border'], { collapse: true })
// TypeError: X is not iterable
```
```js
designSystem.canonicalizeCandidates(['shadow-sm', 'border'], { collapse: true })
// TypeError: Cannot read properties of null (reading 'has')
```
All shadow utilities (`shadow-sm`, `shadow-md`, `shadow-lg`,
`shadow-xl`) crash when combined with any other utility and `collapse:
true`.
This was discovered via `eslint-plugin-better-tailwindcss`, which calls
`canonicalizeCandidates` with `collapse: true` for its
`enforce-canonical-classes` rule. The crash brings down ESLint entirely.
## Root cause
In `collapseGroup`, the `otherUtilities` array is built by mapping over
each candidate's property values:
```ts
let otherUtilities = candidatePropertiesValues.map((propertyValues) => {
let result: Set<string> | null = null
for (let property of propertyValues.keys()) {
// ... builds result ...
}
return result! // returns null if propertyValues has no keys
})
```
When a utility like `shadow-sm` generates CSS with `@property` rules and
custom property declarations but no standard CSS properties,
`propertyValues.keys()` is empty, the loop never executes, and `result`
stays `null`. The non-null assertion `result!` returns `null` into the
array.
Downstream code then crashes when iterating or calling `.has()` on the
null entry:
```ts
for (let i = 0; i < otherUtilities.length; i++) {
let current = otherUtilities[i] // null
for (let property of current) { // "X is not iterable"
if (other.has(property)) { // "Cannot read properties of null"
```
## Fix
Return an empty `Set` instead of `null` when a utility has no property
keys:
```ts
return result ?? new Set<string>()
```
This is semantically correct: a utility with no standard properties
cannot be linked to or collapsed with any other utility, which is
exactly what an empty Set represents in the linking algorithm. It won't
cause false collapses or suppress valid collapses of other utilities.
## Test plan
- Added test: `collapse does not crash when utilities with no standard
properties are present`
- Verifies `shadow-sm + border`, `shadow-md + p-4`, and `shadow-sm +
shadow-md` don't throw
- Verifies the candidates are returned uncollapsed (correct behavior)
- All 1218 existing tests continue to pass
---------
Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
This PR ensures that interpolated expressions in Ruby syntax are
correctly extracted.
The issue was that we ignore comments in Ruby syntax (which start with
`#`). We already made an exception for locals (`<%# locals: … %>`), but
we also need to handle interpolated expressions (`#{ … }`) in the same
way because they are not comments.
Fixes: #19728
## Test plan
1. Existing tests pass
2. Added a regression test for this scenario
3. Tested using the extractor on the given code snippet:
<img width="1461" height="1856" alt="image"
src="https://github.com/user-attachments/assets/b48f7042-ca9d-4133-87ae-4c37c633c073"
/>
Notice that the `w-100` gets extracted now.
When user-controlled candidate values like "constructor" are used as
keys to look up values in plain objects (staticValues, plugin values,
modifiers, config), they can match inherited Object.prototype properties
instead of returning undefined. This caused crashes like "V.map is not
a function" when scanning source files containing strings like
"row-constructor".
Use Object.hasOwn() checks before all user-keyed object lookups in:
- utilities.ts (staticValues lookup)
- plugin-api.ts (values, modifiers, and variant values lookups)
- plugin-functions.ts (get() config traversal function)
Fixes#19721https://claude.ai/code/session_011CYSGw3DLh2Z8xnuyoaCgC
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
## Problem
Tailwind 4.2.0 introduced stricter `@utility` name validation (#19524)
that rejects functional utility names where the root ends with a dash
after stripping the `-*` suffix. This breaks a valid and useful naming
pattern where a double dash separates the CSS property from a value
scale:
```css
@utility border--* {
border-color: --value(--color-border-*, [color]);
}
```
This produces: `border--0`, `border--1`, `border--2`, etc.
The error message is:
> `@utility border--*` defines an invalid utility name. Utilities should
be alphanumeric and start with a lowercase letter.
## Why this pattern matters
The double-dash convention creates a clear visual grammar in class
names. The first segment names the CSS property, and the double dash
separates it from the semantic scale value. In a dense className string
like `border border--0 background--0 content--4`, the scale values (0,
0, 4) are immediately scannable, distinct from the single-dash property
names around them.
This pattern is actively used in production design systems for semantic
color scales (background, content, border, shadow) with values from
0-10.
## Why the restriction is unnecessary
The validation comment states the concern is that `border--*` could
match the bare class `border-` when using default values. However, this
edge case is already handled:
1. **`findRoots` in `candidate.ts`** (line 887) already rejects empty
values: `if (root[1] === '') break`
2. **The Oxide scanner** already extracts double-dash candidates
correctly, as confirmed by existing tests: `("items--center",
vec!["items--center"])`
The candidate parser and scanner both handle this case. The validation
was an overcorrection.
## Changes
- Removed the trailing-dash check from `isValidFunctionalUtilityName` in
`utilities.ts`
- Updated the existing unit test from `['foo--*', false]` to `['foo--*',
true]`
- Added an integration test proving `@utility border--*` compiles
correctly with theme values
## Test results
All 4121 tests pass across the tailwindcss package, including the new
integration test.
---------
Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
I noticed this when reading the changelog to migrate a project to the
new version. I'm not sure whether retroactively changing the changelog
is considered acceptable behaviour in this project or whether appending
a notice in the next changelog would be better.
Funnily this was actually guessed in #19613, though hard to notice among
the other many false guesses.
## Summary
This PR updates outdated GitHub Action versions by migrating
`actions/download-artifact` from `v6` to `v7` in the following
workflows:
- `.github/workflows/prepare-release.yml`
- `.github/workflows/release.yml`
- `.github/workflows/release-insiders.yml`
## Test plan
The changes will be tested in the CI pipeline of the pull request.
[×] Summary
[×] Test plan
## Summary
This PR makes a few small consistency fixes:
- Fix outdated GitHub links that still point to the old
`tailwindcss/tailwindcss` org and update them to
`tailwindlabs/tailwindcss` (README + contributing docs + PR template).
- Fix punctuation in the contributing guide (“i.e., …”).
- Update two test titles to use “cannot” instead of “can not” for
consistency.
No behavior changes.
## Test plan
- Link check (manual): clicked the updated GitHub links in `README.md`,
`.github/CONTRIBUTING.md`, and `.github/PULL_REQUEST_TEMPLATE.md` to
confirm they resolve correctly.
- (Optional) `pnpm test` — not required since changes are
docs/test-title-only.
---------
Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
## Summary
fixes
https://github.com/schoero/eslint-plugin-better-tailwindcss/issues/321
This PR fixes an order-sensitive canonicalization bug. This bug caused
issues when running eslint-plugin-better-tailwindcss as the order in
which files are linted in is not consistent. This caused, in some
scenarios, `canonicalizeCandidates(..., { collapse: true,
logicalToPhysical: true, rem: 16 })` to stop collapsing valid
combinations (for example `h-4 + w-4 -> size-4`) after unrelated prior
calls.
To reproduce this issue:
```
# checkout this branch
$ git checkout c/fix-canonicalizeCandidates
# Revert the fix to the current `main` branch
$ git checkout main ./packages/tailwindcss/src/canonicalize-candidates.ts
# Run the tests
$ pnpm run test
```
This should produce a failure like so:
```
FAIL tailwindcss src/canonicalize-candidates.test.ts > regressions > collapse canonicalization is not affected by previous calls
AssertionError: expected [ 'underline', 'h-4', 'w-4' ] to deeply equal [ 'underline', 'size-4' ]
- Expected
+ Received
[
"underline",
- "size-4",
+ "h-4",
+ "w-4",
]
❯ src/canonicalize-candidates.test.ts:1167:66
1165| designSystem.canonicalizeCandidates(['underline', 'mb-4'], options)
1166|
1167| expect(designSystem.canonicalizeCandidates(target, options)).toEqual(['underline', 'size-4'])
| ^
1168| })
1169| })
```
```
# reset all changes on this branch
git reset --hard
# run the tests again (they should now pass)
pnpm run test
```
The cause of this bug is that the canonicalization caches used
`DefaultMap` in places where lookups were expected to be read-only.
`DefaultMap.get` inserts missing entried, which mutated shared cache
state during intermediate lookups and made later canonicalization
results depend on prior calls.
By replacing the use of `DefaultMap` with a plain `Map`, it avoids
inserting into the map on lookup paths. I've polyfilled
[`Map#getOrInsert`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/getOrInsert)
as it is not widely available yet, and used that where appropriate.
## Test plan
I wrote a test that fails on `main` branch, I then fixed the issue, and
validated that the test now passes.
---------
Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
<!--depfu-start-->
> 👉 **This PR is queued up to get rebased by Depfu**
<!--depfu-end-->
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?
#### ✳️ bun (1.3.7 → 1.3.9) · [Repo](https://github.com/oven-sh/bun)
Sorry, we couldn't find anything useful about this release.
---

[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>
Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
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?
#### ✳️ @types/bun (1.3.7 → 1.3.9) ·
[Repo](https://github.com/DefinitelyTyped/DefinitelyTyped)
Sorry, we couldn't find anything useful about this release.
---

[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>
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?
#### ✳️ enhanced-resolve (5.18.4 → 5.19.0) ·
[Repo](https://github.com/webpack/enhanced-resolve)
<details>
<summary>Release Notes</summary>
<h4><a
href="https://github.com/webpack/enhanced-resolve/releases/tag/v5.19.0">5.19.0</a></h4>
<blockquote><h3 dir="auto">Features</h3>
<ul dir="auto">
<li>Added TsconfigPathsPlugin (replacement for <code
class="notranslate">tsconfig-paths-webpack-plugin</code>) .</li>
</ul></blockquote>
<p><em>Does any of this look wrong? <a
href="feedback">Please
let us know.</a></em></p>
</details>
<details>
<summary>Commits</summary>
<p><a
href="e8a6ac9fdd...24ba233554">See
the full diff on Github</a>. The new version differs by 4 commits:</p>
<ul>
<li><a
href="24ba233554"><code>chore(release):
5.19.0</code></a></li>
<li><a
href="10dc3bc8b8"><code>chore:
update eslint config webpack (#471)</code></a></li>
<li><a
href="0d6c6c0fd9"><code>feat:
added TsconfigPathsPlugin (replacement for
tsconfig-paths-webpack-plugin) (#463)</code></a></li>
<li><a
href="958aa89219"><code>chore:
migrate to npm from yarn (#469)</code></a></li>
</ul>
</details>
---

[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>
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?
#### ✳️ @types/react (19.2.10 → 19.2.14) ·
[Repo](https://github.com/DefinitelyTyped/DefinitelyTyped)
Sorry, we couldn't find anything useful about this release.
---

[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>
## Summary
This PR adds four new neutral color palettes to Tailwind CSS: `mauve`,
`olive`, `mist`, and `taupe`. Each palette includes 11 shades (50, 100,
200, 300, 400, 500, 600, 700, 800, 900, 950) defined using the OKLch
color space for perceptually uniform color transitions.
These new palettes expand the available neutral color options beyond the
existing stone, slate, gray, zinc, and neutral palettes, providing
designers with more nuanced choices for different design systems and
brand aesthetics.
The changes include:
- Added color definitions to `packages/tailwindcss/src/compat/colors.ts`
- Added corresponding CSS custom properties to
`packages/tailwindcss/theme.css`
## Test plan
To verify these changes:
1. Build the project and ensure no compilation errors occur
2. Verify that the new color palettes are available in the Tailwind
config
3. Test that utilities like `bg-mauve-500`, `text-olive-600`,
`border-mist-300`, and `ring-taupe-400` work correctly
4. Confirm that the colors render with proper OKLch values in the
browser
https://claude.ai/code/session_01QhC1ZYkW3pCd55WbbqYBNV
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
## Summary
Update the GitHub Actions CI status badge URLs in `packages/*/README.md`
to track `branch=main` instead of `branch=next`. This matches the root
README, keeps the badges consistent across the repo, and ensures the
displayed CI status reflects the default branch.
## Test plan
Docs-only change.
Verified the updated badge URLs in the modified `packages/*/README.md`
files use `ci.yml?branch=main`.
Resolves#19607
<!--
👋 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 a discussion to
first discuss any significant new features.
For more info, check out the contributing guide:
https://github.com/tailwindcss/tailwindcss/blob/main/.github/CONTRIBUTING.md
-->
## Summary
<!--
Provide a summary of the issue and the changes you're making. How does
your change solve the problem?
-->
I believe there is no obstacle to simply ignoring backslashes in the
name. This way, various validators - which are not aware of Tailwind
CSS's specific syntax (which allows the `/` character to be used
directly in utility names) - can still be bypassed using backslashes.
For example, instead of `@utility push-1/2`, one could use `@utility
push-1\/2`, while the end result would be identical.
## Test plan
<!--
Explain how you tested your changes. Include the exact commands that you
used to verify the change works and include screenshots/screen
recordings of the update behavior in the browser if applicable.
-->
I took a previous utility test as a baseline and extended it with
backslashes, and I expect the same result in the output as in the
original test case:
*
https://github.com/rozsazoltan/tailwindcss/blob/main/packages/tailwindcss/src/utilities.test.ts#L28553-L28567
(the original test case I started from)
*
https://github.com/rozsazoltan/tailwindcss/blob/feat/handle-blackslash-in-utility-name/packages/tailwindcss/src/index.test.ts#L4640-L4654
(the current PR's test)
---------
Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
<!--
👋 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 a discussion to
first discuss any significant new features.
For more info, check out the contributing guide:
https://github.com/tailwindcss/tailwindcss/blob/main/.github/CONTRIBUTING.md
-->
## Summary
Sometimes even if Vite Envrionment API is available, some plugins are
still override `config.createResolver` function to inject own aliases
Since technically `config.createResolver` was only [properly
deprecated](https://github.com/vitejs/vite/pull/20031) in Vite 7.0.0,
it's still a valid(-ish) to do so, even if it wasn't ever officially
supported
Vite already handles this in its internal css resolvers, but not exposes
the code to do so as part of public API, so I've copied and adapted it
Fixes#19677
## Test plan
Tested by copying built package into my repro from the issue, also ran
vite integration tests
---------
Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
This PR improves the performance of Oxide when scanning large codebases.
The `Oxide` API, looks something like this:
```ts
let scanner = new Scanner({ sources })
let candidates = scanner.scan() // Found candidates
let files = scanner.files // Scanned files
let globs = scanner.globs // Scanned globs
```
The `files` and `globs` are used to tell PostCSS, Vite, webpack etc
which files to watch for changes.
The `.scan()` operation extracts the candidates from the source files.
You can think of these as potential Tailwind CSS classes.
In all these scenarios we have to walk the file system and find files
that match the `sources`.
### 1. Prevent multiple file system walks
The first big win came from the fact that accessing `.files` after a
`.scan()` also does an entire walk of the file system (for the given
`sources`), which is unnecessary because we just walked the file system.
This is something that's not really an issue in smaller codebases
because we have `mtime` tracking. We don't re-scan a file if its `mtime`
hasn't changed since the last scan. However, in large codebases with
thousands of files, even walking the file system to check `mtime`s can
be expensive.
### 2. Use parallel file system walking
Another big win is to use a parallel file system walker instead of a
synchronous one. The big problem here is that the parallel build has
20ms-50ms of overhead which is noticeable on small codebases. We don't
really know if you have a small or big codebase ahead of time, so maybe
some kind of hint in the future would be useful.
So the solution I settled on right now is to use a synchronous walker
for the initial scan, and then switch to a parallel walker for
subsequent scans (think dev mode). This gives us the best of both
worlds: fast initial scan on small codebases, and fast re-scans on large
codebases.
Caveat: if you use the `@tailwindcss/cli` we know exactly which files
changed so we can just re-scan those files directly without walking the
file system at all. But in `@tailwindcss/postcss` we don't know which
files changed, so we have to walk the file system to check `mtime`s.
While this improvement is nice, it resulted in an annoying issue related
to `mtime` tracking. Since the parallel walker processes files in
parallel, the `mtime` was typed as `Arc<Mutex<FxHashMap<PathBuf,
SystemTime>>>` so to avoid locking, I decided to only walk the files
here and collect their paths. Then later we check the `mtime` to know
whether to re-scan them or not.
Initially I just removed the `mtime` tracking altogether. But it did
have an impact when actually extracting candidates from those files, so
I added it back later.
### 3. Delaying work
I was still a bit annoyed by the fact that we had to track `mtime`
values for every file. This seems like annoying overhead, especially
when doing a single build (no dev mode).
So the trick I applied here is to only start tracking `mtime` values
after the initial scan.
This means that, in dev mode, we would do this:
1. Walk entire file system to track files.
2. On a subsequent scan, walk entire file system (again) and start
tracking `mtime` values. This time, we use the parallel walker instead
of the synchronous one.
3. On further scans, only re-scan files whose `mtime` has changed
The trade-off here is that on the second scan we always re-scan all
files, even if they haven't changed. Since this typically only happens
in dev mode, I think this is an acceptable trade-off especially if the
initial build is therefor faster this way.
### 3. Small wins
There are also a few small wins in here that I would like to mention but
that are less significant:
1. Pre-computed normalized `source` patterns instead of in every walker
filter call.
2. Tried to avoid some allocations in various places. For example the
`pre_process_input` always called `content.to_vec()` which allocates.
Instead we now accept an owned `Vec<u8>` so we don't have to call
`.to_vec()` in the default case (in my testing, this is ~92% of the time
in the codebases I checked).
3. Made the `Cursor` struct smaller, which is used a lot during
candidate extraction.
### Benchmarks
Now for the fun stuff, the benchmarks!
<details>
<summary>The code for the benchmarks</summary>
```ts
import path from 'node:path'
import { bench, boxplot, do_not_optimize, run, summary } from 'mitata'
import { Scanner as ScannerPr } from '/path/to/repo/with/pr/branch/tailwindcss/crates/node'
import { Scanner as ScannerMain } from '/path/to/repo/with/main/branch/tailwindcss/crates/node'
let base = '/path/to/some/codebase'
let sources = [{ base, pattern: '**/*', negated: false }]
// Verify the results are the same before benchmarking
let scannerPr = new ScannerPr({ sources })
let scannerMain = new ScannerMain({ sources })
{
let aCandidates = scannerPr.scan()
let bCandidates = scannerMain.scan()
if (aCandidates.length !== bCandidates.length) {
throw new Error(`Mismatch in candidate count: ${aCandidates.length} vs ${bCandidates.length}`)
}
for (let i = 0; i < aCandidates.length; i++) {
if (aCandidates[i] !== bCandidates[i]) {
throw new Error(`Mismatch in candidate at index ${i}: ${aCandidates[i]} vs ${bCandidates[i]}`)
}
}
let aFiles = scannerPr.files
let bFiles = scannerMain.files
if (aFiles.length !== bFiles.length) {
throw new Error(`Mismatch in file count: ${aFiles.length} vs ${bFiles.length}`)
}
for (let i = 0; i < aFiles.length; i++) {
if (aFiles[i] !== bFiles[i]) {
throw new Error(`Mismatch in file at index ${i}: ${aFiles[i]} vs ${bFiles[i]}`)
}
}
console.log('Scanned', aFiles.length, 'files')
console.log('Extracted', aCandidates.length, 'candidates')
console.log('Base =', base)
console.log()
}
summary(() => {
boxplot(() => {
bench('PR (build, .scan()))', function* () {
yield {
[0]() {
return new ScannerPr({ sources })
},
bench(scanner: ScannerPr) {
do_not_optimize(scanner.scan())
},
}
})
bench('main (build, .scan()))', function* () {
yield {
[0]() {
return new ScannerMain({ sources })
},
bench(scanner: ScannerMain) {
do_not_optimize(scanner.scan())
},
}
})
})
})
summary(() => {
boxplot(() => {
bench('PR (build, .scan() + .files)', function* () {
yield {
[0]() {
return new ScannerPr({ sources })
},
bench(scanner: ScannerPr) {
do_not_optimize(scanner.scan())
do_not_optimize(scanner.files)
},
}
})
bench('main (build, .scan() + .files)', function* () {
yield {
[0]() {
return new ScannerMain({ sources })
},
bench(scanner: ScannerMain) {
do_not_optimize(scanner.scan())
do_not_optimize(scanner.files)
},
}
})
})
})
summary(() => {
boxplot(() => {
bench('PR (watch, .scan()))', function* () {
yield {
bench() {
do_not_optimize(scannerPr.scan())
},
}
})
bench('main (watch, .scan()))', function* () {
yield {
bench() {
do_not_optimize(scannerMain.scan())
},
}
})
})
})
summary(() => {
boxplot(() => {
bench('PR (watch, .scan() + .files)', function* () {
yield {
bench() {
do_not_optimize(scannerPr.scan())
do_not_optimize(scannerPr.files)
},
}
})
bench('main (watch, .scan() + .files)', function* () {
yield {
bench() {
do_not_optimize(scannerMain.scan())
do_not_optimize(scannerMain.files)
},
}
})
})
})
await run()
```
</details>
#### tailwindcss.com codebase
```
Scanned 462 files
Extracted 13200 candidates
Base = /Users/robin/github.com/tailwindlabs/tailwindcss.com
clk: ~3.09 GHz
cpu: Apple M1 Max
runtime: bun 1.3.3 (arm64-darwin)
```
In these benchmarks the `PR` one is consistently faster than `main`.
It's not by a lot but that's mainly because the codebase itself isn't
that big. It is a codebase with _a lot_ of candidates though, but not
that many files.
The candidate extraction was already pretty fast, so the wins here
mainly come from avoiding re-walking the file system when accessing
`.files`, and from delaying `mtime` tracking until after the initial
scan.
**Single initial build**:
It's not a lot, but it's a bit faster. This is due to avoiding tracking
the `mtime` values initially and making some small optimizations related
to the struct size and allocations.
```
benchmark avg (min … max) p75 / p99 (min … top 1%)
--------------------------------------------- -------------------------------
PR (build, .scan())) 22.87 ms/iter 23.28 ms █
(21.49 ms … 25.68 ms) 23.98 ms ▂ ▂ ▂ █ ▂▂
(832.00 kb … 2.69 mb) 1.41 mb ▆▆▆▆█▆▆█▁▆▆█▁▁█▁▆██▁▆
main (build, .scan())) 25.67 ms/iter 26.12 ms █ █ █
(24.54 ms … 27.74 ms) 27.06 ms █ █ █ ███
(432.00 kb … 2.78 mb) 996.00 kb ██▁████▁█▁████▁█▁▁█▁█
┌ ┐
╷ ┌─────┬──┐ ╷
PR (build, .scan())) ├────┤ │ ├─────┤
╵ └─────┴──┘ ╵
╷ ┌─────┬──┐ ╷
main (build, .scan())) ├──┤ │ ├───────┤
╵ └─────┴──┘ ╵
└ ┘
21.49 ms 24.28 ms 27.06 ms
summary
PR (build, .scan()))
1.12x faster than main (build, .scan()))
```
**Single initial build + accessing `.files`**:
We don't have to re-walk the entire file system even if we're just
dealing with ~462 scanned files.
```
benchmark avg (min … max) p75 / p99 (min … top 1%)
--------------------------------------------- -------------------------------
PR (build, .scan() + .files) 22.54 ms/iter 22.99 ms █ ▂
(21.41 ms … 25.86 ms) 24.26 ms █ ▅ ▅▅█▅ ▅▅
(368.00 kb … 2.05 mb) 853.00 kb █▇█▇▇████▇▇██▁▁▇▁▁▇▁▇
main (build, .scan() + .files) 32.15 ms/iter 32.17 ms █ ▂
(30.78 ms … 36.22 ms) 35.75 ms ▅█ ▅█ ▅
(400.00 kb … 2.45 mb) 952.00 kb ██▁██▇▇█▇▁▁▁▁▁▁▁▁▁▁▁▇
┌ ┐
╷┌──┬┐ ╷
PR (build, .scan() + .files) ├┤ │├───┤
╵└──┴┘ ╵
╷┌───┬ ╷
main (build, .scan() + .files) ├┤ │──────────┤
╵└───┴ ╵
└ ┘
21.41 ms 28.58 ms 35.75 ms
summary
PR (build, .scan() + .files)
1.43x faster than main (build, .scan() + .files)
```
**Watch/dev mode, only scanning**:
This now switches to the parallel walker, but since it's not a super big
codebase we don't see a huge win here yet.
```
benchmark avg (min … max) p75 / p99 (min … top 1%)
--------------------------------------------- -------------------------------
PR (watch, .scan())) 6.85 ms/iter 7.22 ms █▄
(6.34 ms … 7.94 ms) 7.91 ms ▄██▃
( 64.00 kb … 688.00 kb) 452.82 kb ▃████▆▂▂▁▂▁▂▁▁▁▅█▆▃▅▃
main (watch, .scan())) 7.92 ms/iter 8.08 ms █ █ ▃ █▃▃
(7.41 ms … 8.71 ms) 8.68 ms █▆█▆▃█████
( 0.00 b … 64.00 kb) 19.20 kb ▆▄██████████▆▁▆▆█▄▄▄▆
┌ ┐
╷ ┌──────┬──────┐ ╷
PR (watch, .scan())) ├──┤ │ ├────────────┤
╵ └──────┴──────┘ ╵
╷ ┌───┬──┐ ╷
main (watch, .scan())) ├────┤ │ ├───────────┤
╵ └───┴──┘ ╵
└ ┘
6.34 ms 7.51 ms 8.68 ms
summary
PR (watch, .scan()))
1.16x faster than main (watch, .scan()))
```
**Watch/dev mode, scanning + accessing `.files`**:
Again we avoid re-walking the entire file system when accessing
`.files`.
```
benchmark avg (min … max) p75 / p99 (min … top 1%)
--------------------------------------------- -------------------------------
PR (watch, .scan() + .files) 12.10 ms/iter 12.74 ms █ █ █ █ ▃▃▃
(10.69 ms … 13.89 ms) 13.81 ms █ █▂▂▂ ▇█▂█▂███▇
(128.00 kb … 10.73 mb) 5.23 mb █▆████▁█████████▆▆▆▆▆
main (watch, .scan() + .files) 14.44 ms/iter 14.74 ms █
(13.93 ms … 15.33 ms) 15.18 ms ███▅ █ ▅ ▅
( 16.00 kb … 80.00 kb) 39.51 kb █▅████▁███▅▁█████▅▁▅▅
┌ ┐
╷ ┌──────┬──────┐ ╷
PR (watch, .scan() + .files) ├──────┤ │ ├─────────┤
╵ └──────┴──────┘ ╵
╷ ┌───┬──┐ ╷
main (watch, .scan() + .files) ├─┤ │ ├───┤
╵ └───┴──┘ ╵
└ ┘
10.69 ms 12.93 ms 15.18 ms
summary
PR (watch, .scan() + .files)
1.19x faster than main (watch, .scan() + .files)
```
#### Synthetic 5000 files codebase
Based on the instructions from #19616 I created a codebase with 5000
files. Each file contains a `flex` class and a unique class like
`content-['/path/to/file']` to ensure we have a decent amount of unique
candidates.
You can test the script yourself by running this:
```
mkdir -p fixtures/app-5000/src/components/{auth,dashboard,settings,profile,notifications,messages,search,navigation,footer,sidebar}/sub{001..500} && for dir in fixtures/app-5000/src/components/*/sub*; do echo "export const Component = () => <div className=\"flex content-['$dir']\">test</div>" > "$dir/index.tsx"; done && find fixtures/app-5000/src/components -type f | wc -lc
```
```
Scanned 5000 files
Extracted 5005 candidates
Base = /Users/robin/github.com/RobinMalfait/playground/scanner-benchmarks/fixtures/app-5000
clk: ~3.08 GHz
cpu: Apple M1 Max
runtime: bun 1.3.3 (arm64-darwin)
```
**Single initial build**:
As expected not a super big win here because it's a single build. But
there is a noticeable improvement.
```
benchmark avg (min … max) p75 / p99 (min … top 1%)
--------------------------------------------- -------------------------------
PR (build, .scan())) 217.27 ms/iter 211.97 ms █
(205.99 ms … 289.53 ms) 214.33 ms ▅ ▅ ▅▅▅▅█▅▅ ▅
( 3.34 mb … 4.25 mb) 3.72 mb █▁▁▁▁▁▁█▁███████▁▁▁▁█
main (build, .scan())) 249.26 ms/iter 239.88 ms █
(231.51 ms … 381.66 ms) 241.01 ms ▅ ▅ ▅▅ ▅ █▅ ▅▅▅
( 4.22 mb … 4.78 mb) 4.49 mb █▁▁▁▁█▁██▁▁█▁▁██▁▁███
┌ ┐
╷ ┌─────╷──┬
PR (build, .scan())) ├────┤ ┤ │
╵ └─────╵──┴
╷ ┌───────╷
main (build, .scan())) ├───┤ ┤
╵ └───────╵
└ ┘
205.99 ms 223.50 ms 241.01 ms
summary
PR (build, .scan()))
1.15x faster than main (build, .scan()))
```
**Single initial build + accessing `.files`**:
Now things are getting interesting. Almost a 2x speedup by avoiding
re-walking the file system when accessing `.files`.
```
benchmark avg (min … max) p75 / p99 (min … top 1%)
--------------------------------------------- -------------------------------
PR (build, .scan() + .files) 216.35 ms/iter 214.53 ms █ █ █
(211.00 ms … 242.64 ms) 221.45 ms █ █▅█ ▅▅ ▅ ▅
( 2.97 mb … 4.47 mb) 3.97 mb █▁███▁██▁▁▁▁▁▁█▁▁▁▁▁█
main (build, .scan() + .files) 414.79 ms/iter 406.05 ms ██
(396.72 ms … 542.30 ms) 413.69 ms ▅ ██▅ ▅▅ ▅ ▅ ▅
( 5.19 mb … 6.03 mb) 5.63 mb █▁▁▁███▁██▁█▁█▁▁▁▁▁▁█
┌ ┐
┌┬╷
PR (build, .scan() + .files) ││┤
└┴╵
╷┌──╷
main (build, .scan() + .files) ├┤ ┤
╵└──╵
└ ┘
211.00 ms 312.34 ms 413.69 ms
summary
PR (build, .scan() + .files)
1.92x faster than main (build, .scan() + .files)
```
**Watch/dev mode, only scanning**:
This is where we see bigger wins because now we're using the parallel
walker.
```
benchmark avg (min … max) p75 / p99 (min … top 1%)
--------------------------------------------- -------------------------------
PR (watch, .scan())) 76.26 ms/iter 77.41 ms █
(73.56 ms … 79.02 ms) 77.81 ms ▅ ▅ ▅ ▅▅ ▅▅▅ ▅ █
( 2.53 mb … 5.52 mb) 3.06 mb █▁▁▁█▁▁█▁██▁███▁▁▁█▁█
main (watch, .scan())) 166.71 ms/iter 165.14 ms █ █
(161.49 ms … 198.26 ms) 168.99 ms █ ▅█ ▅▅▅ ▅ ▅ ▅
( 1.08 mb … 2.72 mb) 1.24 mb █▁██▁███▁▁█▁▁█▁▁▁▁▁▁█
┌ ┐
╷┬┐
PR (watch, .scan())) ├││
╵┴┘
╷┌─┬╷
main (watch, .scan())) ├┤ │┤
╵└─┴╵
└ ┘
73.56 ms 121.28 ms 168.99 ms
summary
PR (watch, .scan()))
2.19x faster than main (watch, .scan()))
```
**Watch/dev mode, scanning + accessing `.files`**:
This is the biggest win of them all because we have all the benefits
combined:
1. Avoiding re-walking the file system when accessing `.files`
2. Using the parallel walker for faster file system walking
```
benchmark avg (min … max) p75 / p99 (min … top 1%)
--------------------------------------------- -------------------------------
PR (watch, .scan() + .files) 84.04 ms/iter 84.84 ms █
(80.96 ms … 87.53 ms) 87.27 ms ▅▅ ▅▅ ▅▅ █▅ ▅ ▅
( 15.42 mb … 31.34 mb) 22.16 mb ██▁▁▁██▁██▁██▁█▁▁▁▁▁█
main (watch, .scan() + .files) 338.59 ms/iter 353.89 ms █
(321.87 ms … 378.43 ms) 358.70 ms █ █
( 2.39 mb … 2.45 mb) 2.42 mb ███▁▁██▁▁▁▁▁▁▁▁▁▁██▁█
┌ ┐
┬┐
PR (watch, .scan() + .files) ││
┴┘
┌──┬─┐╷
main (watch, .scan() + .files) │ │ ├┤
└──┴─┘╵
└ ┘
80.96 ms 219.83 ms 358.70 ms
summary
PR (watch, .scan() + .files)
4.03x faster than main (watch, .scan() + .files)
```
## Test plan
1. All existing tests still pass
2. All public APIs remain the same
3. In the benchmarks I'm sharing, I first verify that the candidates
returned and the files returned are the same before and after the
change.
4. Benchmarked against real codebases, and against a synthetic large
codebase (5000 files).
Fixes: #19616
# PR: Fix @source file changes not triggering full page reload on Vite
7.1+
## Description
This PR addresses issue #19637 where template files (PHP, HTML, Blade,
etc.) watched via the `@source` directive fail to trigger a full page
reload when using Vite 7.1 or newer.
## Root Cause
Vite 7.1 introduced the Environment API, which supersedes the legacy
WebSocket API for HMR. Specifically:
- `server.ws.send` is deprecated/ignored for certain external file
updates in favor of `server.hot.send`.
- The `@tailwindcss/vite` plugin currently collects `ViteDevServer`
instances but lacks a `handleHotUpdate` hook to explicitly trigger
reloads for non-module files added via `addWatchFile`.
## Changes
- Implemented a `handleHotUpdate` hook in the `@tailwindcss/vite`
plugin.
- The hook identifies changes to files that are not part of the standard
Vite module graph (e.g., `.php`, `.html`) but are watched by Tailwind.
- Triggers a `full-reload` using the new `server.hot.send` API if
available (Vite 7.1+), with a fallback to `server.ws.send` for backward
compatibility.
## Verification
- Reproduced the issue in a standalone Vite 7.1.0 project using a mock
plugin with the legacy API.
- Confirmed that the browser fails to reload upon editing a watched
`.php` file.
- Verified that migrating to `server.hot.send` restores the expected
reload behavior.
[ci-all]
---------
Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
This PR reduces the restrictions of the `aspect-*` utilities when
dealing with fractional values.
Up until now, the numbers had to be positive integers, so `aspect-1/2`
was valid, but `aspect-8.5/11` was not.
This PR allows for any multiple of `.25` as a valid value, so
`aspect-8.5/11` is now valid, but `aspect-8.3/11` is not, this will
still require `aspect-[8.3/11]` arbitrary value syntax to be valid.
This behavior of allowing multiples of `.25` is consistent with other
utilities that handle bare values such as `w-2.5`.
## Test plan
1. Existing tests pass
2. Added a test for `aspect-8.5/11`
Fixes: #19663Closes: #19680, #19669
## Summary
Fix outdated GitHub links that still point to
`github.com/tailwindcss/tailwindcss` (old org). This updates references
across the README, contributing guide, and PR template to the canonical
`tailwindlabs/tailwindcss` URLs to avoid redirects/404s and keep repo
metadata consistent
## Test Plan
This change is docs-only.
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?
#### ✳️ @vitejs/plugin-react (5.1.2 → 5.1.3) ·
[Repo](https://github.com/vitejs/vite-plugin-react) ·
[Changelog](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/CHANGELOG.md)
---

[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>
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?
#### ✳️ autoprefixer (10.4.23 → 10.4.24) ·
[Repo](https://github.com/postcss/autoprefixer) ·
[Changelog](https://github.com/postcss/autoprefixer/blob/main/CHANGELOG.md)
<details>
<summary>Release Notes</summary>
<h4><a
href="https://github.com/postcss/autoprefixer/releases/tag/10.4.24">10.4.24</a></h4>
<blockquote><ul dir="auto">
<li>Made Autoprefixer a little faster (by <a
href="https://bounce.depfu.com/github.com/Cherry">@Cherry</a>).</li>
</ul></blockquote>
<p><em>Does any of this look wrong? <a
href="feedback">Please let
us know.</a></em></p>
</details>
<details>
<summary>Commits</summary>
<p><a
href="212ba3c189...36692c25e7">See
the full diff on Github</a>. The new version differs by 3 commits:</p>
<ul>
<li><a
href="36692c25e7"><code>Release
10.4.24 version</code></a></li>
<li><a
href="67df014ae1"><code>Update
dependencies</code></a></li>
<li><a
href="032440ee4a"><code>perf:
reduce array allocations (#1542)</code></a></li>
</ul>
</details>
---

[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>
<!--
👋 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 a discussion to
first discuss any significant new features.
For more info, check out the contributing guide:
https://github.com/tailwindcss/tailwindcss/blob/main/.github/CONTRIBUTING.md
-->
## Summary
These package READMEs referenced the wrong GitHub org
(tailwindcss/tailwindcss) and outdated branches (master/next) for common
project links.
Update them to point at tailwindlabs/tailwindcss on main for releases,
license, discussions, and contributing docs.
<!--
Provide a summary of the issue and the changes you're making. How does
your change solve the problem?
-->
## Test plan
Docs-only change: No test required.
<!--
Explain how you tested your changes. Include the exact commands that you
used to verify the change works and include screenshots/screen
recordings of the update behavior in the browser if applicable.
-->
<!--
👋 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 a discussion to
first discuss any significant new features.
For more info, check out the contributing guide:
https://github.com/tailwindcss/tailwindcss/blob/main/.github/CONTRIBUTING.md
-->
## Summary
The README still referenced the `next` branch for the CI badge and
contributing docs link, but the `next` branch no longer exists upstream.
This updates those URLs to point to `main` so the badge and contributing
docs link work correctly.
<!--
Provide a summary of the issue and the changes you're making. How does
your change solve the problem?
-->
## Test plan
N/A, docs only change
<!--
Explain how you tested your changes. Include the exact commands that you
used to verify the change works and include screenshots/screen
recordings of the update behavior in the browser if applicable.
-->
<!--
👋 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 a discussion to
first discuss any significant new features.
For more info, check out the contributing guide:
https://github.com/tailwindcss/tailwindcss/blob/main/.github/CONTRIBUTING.md
-->
## Summary
The README license badge linked to a non-existent `master` branch (and
the wrong org).
This updates the link to the current location:
tailwindlabs/tailwindcss/blob/main/LICENSE.
<!--
Provide a summary of the issue and the changes you're making. How does
your change solve the problem?
-->
## Test plan
- Opened `README.md` and clicked the license badge/link to confirm it
resolves to the LICENSE file on the `main` branch.
<!--
Explain how you tested your changes. Include the exact commands that you
used to verify the change works and include screenshots/screen
recordings of the update behavior in the browser if applicable.
-->