google-labs-code / google-labs-code/design.md
No way to declare intentional component sub-tokens, so every recipe warns
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 28k
- Forks
- 2.3k
- PR merge metrics
- No merged PRs in 30d
Description
Custom component sub-tokens already work: they parse, their token references resolve, and they survive into the resolved model, so a project can build on them. design.md lint exits 0. The gap is that there's no way to tell the linter which ones are intentional, so broken-ref warns once per recipe, forever.
Our design system records two sub-tokens per recipe that the exporter schema doesn't define: owner, the canonical code module implementing the recipe, and gap, a resolved spacing value for compositions that own the spacing between their children. Our build step reads the linter's resolved model and generates a typed contract from both.
That's 49 of our 62 warnings today, growing with every component. The cost isn't the volume, it's that a misspelled sub-token produces a warning that reads identically to the 48 expected ones — the check's real value is buried by its own false positives.
Blanket suppression isn't what we want, and it isn't really available anyway: the sub-token check lives inside broken-ref alongside dangling-reference errors, so deselecting the rule through LintOptions.rules would silence genuine errors. Since 0.4.0 we post-process the report instead, matching finding.rule plus the token path against a list of extensions we declare ourselves — which works, but means we maintain the typo defense the linter could be providing.
What would solve it, in order of preference:
- Per-rule options. A way to pass configuration to a rule — for broken-ref, the set of sub-token names the project owns. Validation then runs against the union, and anything unlisted still warns. This generalizes past our case; sub-tokens just happen to be where we hit it first.
- A frontmatter declaration, so the extension names live next to the recipes that use them and travel with the document.
- A documented extension prefix such as x-owner, treated as always-valid. Cheapest to implement, but it renames keys in every recipe and in the resolved model.
Any of these lets a project keep the typo detection instead of reimplementing it. Happy to send a PR in whichever direction you prefer.
Checked in 0.3.0 and 0.4.0: VALID_COMPONENT_SUB_TOKENS, the broken-ref implementation, and LintOptions are identical. loadSpecConfig(filePath?) accepts a path but getSpecConfig() calls it with no argument and it isn't exported. The 0.4.0 omitted: key covers section-level omissions, not sub-tokens.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading the broken-ref implementation, VALID_COMPONENT_SUB_TOKENS, and LintOptions, then inspect how design.md lint produces resolved-model findings. Determine how per-rule configuration could declare owned sub-token names while preserving warnings for unlisted names and dangling references. Done means intentional sub-tokens no longer produce repeated warnings, while misspelled or unresolved references still do.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- tooling
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100