diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b327610b..c84cf0858 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Ensure `@tailwindcss/cli` in `--watch` mode doesn't crash on Windows when `@source` points to a directory that doesn't exist ([#20242](https://github.com/tailwindlabs/tailwindcss/pull/20242)) - Ensure `@tailwindcss/vite` doesn't crash in Deno v2.8.x when `context.parentURL` is not a valid URL ([#20245](https://github.com/tailwindlabs/tailwindcss/pull/20245)) - Ensure `@tailwindcss/cli` in `--watch` mode rebuilds when the input CSS file changes in an ignored directory ([#20246](https://github.com/tailwindlabs/tailwindcss/pull/20246)) +- Ensure `@variant` rules generated by `addBase` can use custom variants defined later ([#20247](https://github.com/tailwindlabs/tailwindcss/pull/20247)) ## [4.3.1] - 2026-06-12 diff --git a/packages/tailwindcss/src/compat/plugin-api.test.ts b/packages/tailwindcss/src/compat/plugin-api.test.ts index ff6bdce2f..e3ea3fb07 100644 --- a/packages/tailwindcss/src/compat/plugin-api.test.ts +++ b/packages/tailwindcss/src/compat/plugin-api.test.ts @@ -1527,6 +1527,41 @@ describe('addBase', () => { " `) }) + + test('@variant inside addBase works with custom variants', async () => { + expect( + await compileCss( + css` + @plugin "my-plugin"; + + @custom-variant custom (&.custom); + `, + { + loadModule: async () => ({ + path: '', + base: '/root', + module: plugin(function ({ addBase }) { + addBase({ + ':root': { + '@variant custom': { + '--x': '1', + }, + }, + }) + }), + }), + }, + ), + ).toMatchInlineSnapshot(` + " + @layer base { + :root.custom { + --x: 1; + } + } + " + `) + }) }) describe('addVariant', () => { diff --git a/packages/tailwindcss/src/compat/plugin-api.ts b/packages/tailwindcss/src/compat/plugin-api.ts index 20ecb14ae..af6e98d77 100644 --- a/packages/tailwindcss/src/compat/plugin-api.ts +++ b/packages/tailwindcss/src/compat/plugin-api.ts @@ -13,12 +13,7 @@ import { escape } from '../utils/escape' import { inferDataType } from '../utils/infer-data-type' import { segment } from '../utils/segment' import { toKeyPath } from '../utils/to-key-path' -import { - compoundsForSelectors, - IS_VALID_VARIANT_NAME, - substituteAtSlot, - substituteAtVariant, -} from '../variants' +import { compoundsForSelectors, IS_VALID_VARIANT_NAME, substituteAtSlot } from '../variants' import { walk, WalkAction } from '../walk' import type { ResolvedConfig, UserConfig } from './config/types' import { createThemeFn } from './plugin-functions' @@ -115,7 +110,6 @@ export function buildPluginApi({ if (referenceMode) return let baseNodes = objectToAst(css) featuresRef.current |= substituteFunctions(baseNodes, designSystem) - featuresRef.current |= substituteAtVariant(baseNodes, designSystem) let rule = atRule('@layer', 'base', baseNodes) walk([rule], (node) => { node.src = src