Allow @variant to be used inside addBase (#19480)

This seems like an unintentional omission

---------

Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
This commit is contained in:
Jordan Pittman 2026-06-04 06:46:40 -04:00 • committed by GitHub
parent d42b34abbf
commit ad6693906a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 57 additions and 1 deletions

View file

@ -26,6 +26,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Ensure standalone `@tailwindcss/cli` binaries are ignored when scanning for class candidates ([#20139](https://github.com/tailwindlabs/tailwindcss/pull/20139))
- Ensure class candidates are extracted from Twig `addClass(…)` and `removeClass(…)` calls ([#20198](https://github.com/tailwindlabs/tailwindcss/pull/20198))
- Don't crash in the Ruby or Vue preprocessors when scanning files containing invalid UTF-8 bytes ([#19588](https://github.com/tailwindlabs/tailwindcss/pull/19588))
- Allow `@variant` to be used inside `addBase` ([#19480](https://github.com/tailwindlabs/tailwindcss/pull/19480))
### Changed

View file

@ -1478,6 +1478,55 @@ describe('addBase', () => {
"
`)
})
test('@variant is replaced inside rules using addBase', async () => {
expect(
await compileCss(
css`
@plugin "my-plugin";
@theme {
--breakpoint-supertiny: 128px;
}
`,
{
loadModule: async () => ({
path: '',
base: '/root',
module: plugin(function ({ addBase }) {
addBase({
':root': {
'@variant supertiny': {
'--PascalCase': '1',
'--camelCase': '1',
'--UPPERCASE': '1',
},
'@variant data-enabled:focus, disabled': {
'--x': '1',
},
},
})
}),
}),
},
),
).toMatchInlineSnapshot(`
"
@layer base {
@media (min-width: 128px) {
:root {
--PascalCase: 1;
--camelCase: 1;
--UPPERCASE: 1;
}
}
:root[data-enabled]:focus, :root:disabled {
--x: 1;
}
}
"
`)
})
})
describe('addVariant', () => {

View file

@ -13,7 +13,12 @@ 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 } from '../variants'
import {
compoundsForSelectors,
IS_VALID_VARIANT_NAME,
substituteAtSlot,
substituteAtVariant,
} from '../variants'
import { walk, WalkAction } from '../walk'
import type { ResolvedConfig, UserConfig } from './config/types'
import { createThemeFn } from './plugin-functions'
@ -110,6 +115,7 @@ 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