docs(skill): say what decides static extraction, and never author a CSS file - #665
Merged
Merged
Conversation
…SS file Three sections already told parts of one rule without ever stating it - `Dynamic Values = CSS Variables`, `$token Scope` and `Inline Variant Pattern` - and none of them said why. An agent that only has the examples pattern matches; one that has the rule generalises to the cases the examples do not cover. The rule, verified against `extract_style_from_member_expression.rs`: an inline `ObjectExpression` or `ArrayExpression` indexed at a style prop extracts to static classes, while an `Identifier` - an object declared elsewhere and reached by name - takes the `dynamic_style` path and becomes a CSS variable. This is the answer given in #663, with the reason attached: a value reached through a variable may have been mutated before it runs, and TypeScript's types are not a runtime guarantee. Adds the detection signal too, from the same issue. Inline CSS variables on the rendered element are how you tell which path you got, and nothing here previously said so. Adds the `css()` exception, which resolves a contradiction the rule creates without it: an external object of `css()` results is fine, because `css()` already extracted at its own call site and `className` is never a style-extraction source. Without stating that, "no external style objects" reads as forbidding the standard variant-map pattern. Adds a section saying not to author `.css`/`.scss` at all. The anti-pattern table forbade `style={{}}`, `styled()` and `stylex.create()`, so writing a stylesheet and importing it was never on the list - and a hand-written stylesheet is invisible to extraction, competing silently with the generated classes. `@devup-ui/reset-css` had no mention anywhere despite needing `include` plus two Vite resolver settings to emit anything, which had to be reverse-engineered out of `node_modules`. Finally, notes that the Vite plugin does not mean the project is a Vite SPA. `vinext` runs Next App Router on Vite, so an App Router project has a `vite.config.ts`, no `next.config.ts`, and uses this plugin - and the Vite section being first made that misreading easy to confirm.
Contributor
Author
|
CI note: the three failing jobs ( This branch differs from A markdown file cannot make generated CSS property types stale. The generated file is behind whatever I have deliberately not regenerated it here — that is a build fix and does not belong inside a docs-only PR — but it will block anything else opened against |
Contributor
Changepacks@devup-ui/components@0.1.55 → 0.1.56 - packages/components/package.jsonPatch
@devup-ui/react@1.0.41 → 1.0.42 - packages/react/package.jsonPatch
@devup-ui/reset-css@1.0.28 → 1.0.29 - packages/reset-css/package.jsonPatch
|
Codecov Report✅ All modified and coverable lines are covered by tests. 🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #663.
Why
Three sections of
SKILL.mdalready told parts of one rule without ever stating it —Dynamic Values = CSS Variables,$token Scope, andInline Variant Pattern— and none of them said why. An agent that only has the examples pattern-matches; one that has the rule generalises to the cases the examples do not cover.#663 asked exactly that question, and the answer there is the missing rule.
The rule, verified against the extractor
Not assumed — read out of
libs/extractor/src/extractor/extract_style_from_member_expression.rs:mem.objectArrayExpression(inline)ObjectExpression(inline)Identifier(declared elsewhere, reached by name)dynamic_style()Stated in the skill as:
What this adds
The detection signal, from the issue body. Nothing previously told a reader how to check which path they got:
The flat external-object case. The existing
AVOIDexample wassizeStyles[size].h— nested, with a property access. The issue's actual code wascolors[color]— flat. Same trap, different shape.The
css()exception, which resolves a contradiction the rule creates without it. An external object ofcss()results is fine:css()already extracted at its own call site, andclassNameis never a style-extraction source — it appears nowhere inextract_style_from_jsx.rs, andprop_modify_utils.rsonly merges it ([className, "class-name"].filter(Boolean).join()). Without saying so, "no external style objects" reads as forbidding the standard variant-map pattern.Never author a CSS file. The anti-pattern table forbade
style={{}},styled()andstylex.create()— so writing a stylesheet and importing it was simply never on the list. A hand-written stylesheet is invisible to extraction and competes silently with the generated classes.@devup-ui/reset-css, which had zero mentions anywhere despite needingincludeplus two Vite resolver settings before it emits anything. That combination currently has to be reverse-engineered out ofnode_modules:A vinext note on the Vite section. The Vite plugin does not mean the project is a Vite SPA —
vinextruns Next App Router on Vite, so an App Router project has avite.config.ts, nonext.config.ts, and uses this plugin. The Vite section being listed first made that misreading easy to confirm, and it has already produced a hand-rolled SPA in a real App Router project.Scope
Docs only —
SKILL.md, +93 lines..changepacks/config.jsontrackspackages/*/*, so no changepack applies.