Skip to content

add scope at-rule support#1720

Open
cahnory wants to merge 2 commits intovanilla-extract-css:masterfrom
cahnory:scope-rule
Open

add scope at-rule support#1720
cahnory wants to merge 2 commits intovanilla-extract-css:masterfrom
cahnory:scope-rule

Conversation

@cahnory
Copy link
Copy Markdown

@cahnory cahnory commented Apr 11, 2026

Add support for @scope rules

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Apr 11, 2026

🦋 Changeset detected

Latest commit: eb1de2b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 11 packages
Name Type
@vanilla-extract/css Minor
@vanilla-extract/compiler Patch
@vanilla-extract/integration Patch
@vanilla-extract/rollup-plugin Patch
@vanilla-extract/turbopack-plugin Patch
@vanilla-extract/vite-plugin Patch
@vanilla-extract/esbuild-plugin Patch
@vanilla-extract/jest-transform Patch
@vanilla-extract/parcel-transformer Patch
@vanilla-extract/webpack-plugin Patch
@vanilla-extract/next-plugin Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@cahnory
Copy link
Copy Markdown
Author

cahnory commented Apr 15, 2026

I'm having some trouble running the e2e tests locally on my machine, and I'd really appreciate a bit of help if anyone has an idea what I might be missing. I'm on macOS, in case that makes a difference.

@askoufis
Copy link
Copy Markdown
Contributor

I'm having some trouble running the e2e tests locally on my machine, and I'd really appreciate a bit of help if anyone has an idea what I might be missing. I'm on macOS, in case that makes a difference.

They can be a bit temperamental. Usually running a pnpm build before pnpm playwright should be all that's necessary. Happy to help out further on discord (or elsewhere) if you want.

@cahnory
Copy link
Copy Markdown
Author

cahnory commented Apr 16, 2026

I'm having some trouble running the e2e tests locally on my machine, and I'd really appreciate a bit of help if anyone has an idea what I might be missing. I'm on macOS, in case that makes a difference.

They can be a bit temperamental. Usually running a pnpm build before pnpm playwright should be all that's necessary. Happy to help out further on discord (or elsewhere) if you want.

I just tried running the e2e tests locally on master and got the same result, so it doesn’t seem to be caused by my changes (at least not all errors ^^).

The main issue I’m seeing locally is that the tests appear to be picking up development class names in a production context, for example .themes_responsiveTheme__cdwe0ve instead of .cdwe0ve.

What makes this harder to reason about is that CI is also failing, but with different errors:
https://github.com/cahnory/vanilla-extract/actions/runs/24511603102/job/71643966254

I really don't know what to do :/

@cahnory
Copy link
Copy Markdown
Author

cahnory commented Apr 17, 2026

@askoufis The e2e test issues were caused by parallelization. Since the tests write files, multiple workers were stepping on each other, and limiting the worker count to 1 fixed everything.

I was then able to generate the correct snapshots/screenshots, and the tests are now passing:
https://github.com/cahnory/vanilla-extract/actions/runs/24556048277

Thanks again for your help on Discord!

@tomahl
Copy link
Copy Markdown

tomahl commented Apr 17, 2026

@cahnory glad to see this PR. 👍 Does it support scope limit selectors @scope (scope root) to (scope limit)?

@cahnory
Copy link
Copy Markdown
Author

cahnory commented Apr 17, 2026

@cahnory glad to see this PR. 👍 Does it support scope limit selectors @scope (scope root) to (scope limit)?

Yes it does as the "query" part (what follows @scope ) is not validated. The same treament as for selectors is applied (TL;DR: you can use classes generated by vanilla-extract and the & character).

RegExp('(?<=^(?:[^"\']*|"[^"]*"|\'[^\']*\')*)&', 'g'),
root.selector,
),
)}`;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit confused by this. What is this regex doing? Is there a reason why this.transformSelector(selector.replace(RegExp('&', 'g'), root.selector)) wouldn't work here?

Copy link
Copy Markdown
Author

@cahnory cahnory Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The regex is there to avoid replacing & characters that appear inside quoted strings.

For example, if a selector contains something like [data-value="foo&bar"], a plain selector.replace(/&/g, root.selector) would also replace the & inside "foo&bar", which is not what we want.

I do see a fix to make though. It should probably use:
/(?<=^(?:[^"']*|"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*')*)&/g

That way it only matches & outside quoted strings, while still handling escaped quotes correctly.

I should probably add a few tests for that as well.

You can play with a few examples here:
https://regex101.com/?regex=%28%3F%3C%3D%5E%28%3F%3A%5B%5E%22%5C%27%5D*%7C%22%28%3F%3A%5C%5C.%7C%5B%5E%22%5C%5C%5D%29*%22%7C%5C%27%28%3F%3A%5C%5C.%7C%5B%5E%27%5C%5C%5D%29*%5C%27%29*%29%26&testString=%26%3Abefore%2C+%26%3Aafter%0A%26%5Btitle%3D%22this+%26+that%22%5D%2C+%26%3Aafter%0A%26%5Btitle%3D%22this+%27%26%27+that%22%5D%2C+%26%3Aafter%0A%26%5Btitle%3D%22this+%5C%22%26%5C%22+that%22%5D%2C+%26%3Aafter%0A%26%5Btitle%3D%22thi%5Cs+%5C%5C%26+that%22%5D%2C+%26%3Aafter%0A%0A%26%3Abefore%2C+%26%3Aafter%0A%26%5Btitle%3D%27this+%26+that%27%5D%2C+%26%3Aafter%0A%26%5Btitle%3D%27this+%22%26%22+that%27%5D%2C+%26%3Aafter%0A%26%5Btitle%3D%27this+%5C%27%26%5C%27+that%27%5D%2C+%26%3Aafter%0A%26%5Btitle%3D%27thi%5Cs+%5C%5C%26+that%27%5D%2C+%26%3Aafter&flags=gm&flavor=javascript&delimiter=%2F

};
}

if (condition['@scope']) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Usage of this should be added to the sprinkles fixture.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’ve addressed your other requests locally. Since I’m not using sprinkles, this one will take me a bit more time—I’ll try to get it done quickly!

Comment thread .changeset/thirty-suns-show.md Outdated
Comment on lines +12 to +17
'@scope': {
'(body)': {
':after': { content: '"Scoped to body"' },
},
},
});
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation seems inconsistent here.

Suggested change
'@scope': {
'(body)': {
':after': { content: '"Scoped to body"' },
},
},
});
'@scope': {
'(body)': {
':after': { content: '"Scoped to body"' },
},
},
});

Comment thread packages/css/src/transformCss.test.ts Outdated
`);
});

it('should handle complexe @scope query', () => {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
it('should handle complexe @scope query', () => {
it('should handle complex @scope query', () => {

'@vanilla-extract/css': minor
---

`style`: Add support for `@scope` rules
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

globalStyle should also support @scope now too. Worth adding that to the changeset.

- fix changeset example indentation
- add globalStyle example to changeset
- fix typo in unit test title
- better test for '&' replacement regex
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants