Skip to content

Commit dc6a3ce

Browse files
Substitute @variant inside utilities (#19263)
Fixes #19258
1 parent babe825 commit dc6a3ce

File tree

3 files changed

+69
-5
lines changed

3 files changed

+69
-5
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Fixed
11+
12+
- Substitute `@variant` inside legacy JS APIs ([#19263](https://github.com/tailwindlabs/tailwindcss/pull/19263))
13+
1014
### Added
1115

1216
- _Experimental_: Add `@container-size` utility ([#18901](https://github.com/tailwindlabs/tailwindcss/pull/18901))

packages/tailwindcss/src/design-system.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import { Theme, ThemeOptions, type ThemeKey } from './theme'
2323
import { Utilities, createUtilities, withAlpha } from './utilities'
2424
import { DefaultMap } from './utils/default-map'
2525
import { extractUsedVariables } from './utils/variables'
26-
import { Variants, createVariants } from './variants'
26+
import { Variants, createVariants, substituteAtVariant } from './variants'
2727

2828
export const enum CompileAstFlags {
2929
None = 0,
@@ -77,15 +77,21 @@ export function buildDesignSystem(theme: Theme): DesignSystem {
7777
return new DefaultMap<Candidate>((candidate) => {
7878
let ast = compileAstNodes(candidate, designSystem, flags)
7979

80-
// Arbitrary values (`text-[theme(--color-red-500)]`) and arbitrary
81-
// properties (`[--my-var:theme(--color-red-500)]`) can contain function
82-
// calls so we need evaluate any functions we find there that weren't in
83-
// the source CSS.
8480
try {
81+
// Arbitrary values (`text-[theme(--color-red-500)]`) and arbitrary
82+
// properties (`[--my-var:theme(--color-red-500)]`) can contain function
83+
// calls so we need evaluate any functions we find there that weren't in
84+
// the source CSS.
8585
substituteFunctions(
8686
ast.map(({ node }) => node),
8787
designSystem,
8888
)
89+
90+
// JS plugins might contain an `@variant` inside a generated utility
91+
substituteAtVariant(
92+
ast.map(({ node }) => node),
93+
designSystem,
94+
)
8995
} catch (err) {
9096
// If substitution fails then the candidate likely contains a call to
9197
// `theme()` that is invalid which may be because of incorrect usage,

packages/tailwindcss/src/index.test.ts

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4665,6 +4665,60 @@ test('addBase', async () => {
46654665
`)
46664666
})
46674667

4668+
test('JS APIs support @variant', async () => {
4669+
let { build } = await compile(
4670+
css`
4671+
@plugin "my-plugin";
4672+
@layer base, utilities;
4673+
@layer utilities {
4674+
@tailwind utilities;
4675+
}
4676+
`,
4677+
{
4678+
loadModule: async () => ({
4679+
path: '',
4680+
base: '/root',
4681+
module: ({ addBase, addUtilities, matchUtilities }: PluginAPI) => {
4682+
addBase({ body: { '@variant dark': { color: 'red' } } })
4683+
addUtilities({ '.foo': { '@variant dark': { '--foo': 'foo' } } })
4684+
matchUtilities(
4685+
{ bar: (value) => ({ '@variant dark': { '--bar': value } }) },
4686+
{ values: { one: '1' } },
4687+
)
4688+
},
4689+
}),
4690+
},
4691+
)
4692+
4693+
let compiled = build(['underline', 'foo', 'bar-one'])
4694+
4695+
expect(optimizeCss(compiled).trim()).toMatchInlineSnapshot(`
4696+
"@layer base {
4697+
@media (prefers-color-scheme: dark) {
4698+
body {
4699+
color: red;
4700+
}
4701+
}
4702+
}
4703+
4704+
@layer utilities {
4705+
.underline {
4706+
text-decoration-line: underline;
4707+
}
4708+
4709+
@media (prefers-color-scheme: dark) {
4710+
.bar-one {
4711+
--bar: 1;
4712+
}
4713+
4714+
.foo {
4715+
--foo: foo;
4716+
}
4717+
}
4718+
}"
4719+
`)
4720+
})
4721+
46684722
it("should error when `layer(…)` is used, but it's not the first param", async () => {
46694723
await expect(async () => {
46704724
return await compileCss(

0 commit comments

Comments
 (0)