Skip to content

Commit e5cce25

Browse files
committed
Fix @scope variant output and add test for scoped variant
1 parent 5bc90dd commit e5cce25

File tree

2 files changed

+54
-0
lines changed

2 files changed

+54
-0
lines changed

packages/tailwindcss/src/ast.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,18 @@ export function optimizeAst(
323323

324324
if (nodes.length === 0) return
325325

326+
327+
328+
if (
329+
nodes.length === 1 &&
330+
nodes[0].kind === 'at-rule' &&
331+
(nodes[0].name === '@media' || nodes[0].name === '@supports' || nodes[0].name === '@container' || nodes[0].name === '@scope')
332+
) {
333+
let at = nodes[0]
334+
parent.push(atRule(at.name, at.params, [styleRule(node.selector, at.nodes)]))
335+
return
336+
}
337+
326338
// Rules with `&` as the selector should be flattened
327339
if (node.selector === '&') {
328340
parent.push(...nodes)
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { test, expect } from 'vitest'
2+
import { compile } from '.'
3+
import type { PluginAPI } from './compat/plugin-api'
4+
5+
const css = String.raw
6+
7+
test('custom variants using @scope should wrap correctly', async () => {
8+
let compiler = await compile(
9+
css`
10+
@theme {
11+
--color-red-500: #ef4444;
12+
}
13+
@tailwind utilities;
14+
@plugin 'my-plugin';
15+
`,
16+
{
17+
loadModule: async (id) => {
18+
if (id === 'my-plugin') {
19+
return {
20+
path: '',
21+
base: '',
22+
module: ({ addVariant }: PluginAPI) => {
23+
addVariant('scoped', '@scope (.theme) { & }')
24+
},
25+
}
26+
}
27+
return { path: '', base: '', module: () => {} }
28+
},
29+
},
30+
)
31+
32+
let result = compiler.build(['scoped:bg-red-500'])
33+
34+
// 👇 Move your debug log here
35+
console.log('\n\n=== GENERATED CSS ===\n', result, '\n====================\n\n')
36+
37+
expect(result).toContain('@scope (.theme)')
38+
expect(result).toContain('.scoped\\:bg-red-500')
39+
// The @scope at-rule should wrap the selector: @scope { .selector { ... } }
40+
expect(result.indexOf('@scope')).toBeLessThan(result.indexOf('.scoped\\:bg-red-500'))
41+
42+
})

0 commit comments

Comments
 (0)