feat(design-tokens): complete the CSS-var surface so the website can leave inline styles - #845
Merged
Conversation
…dings
A visual review of the docs site found a set of measured defects: both sticky
rails are dead site-wide (body overflow-x makes <body> a scroll container),
.docs-table-scroll never scrolls because the table is width:100% with no
min-width, and no scroll-margin exists so every deep link lands behind the
81px fixed nav.
Roughly half the fixes are inexpressible in the inline style={{}} objects the
components use, so the work decomposes into three projects: token CSS-var
completion, substrate migration, then the polish arc.
Adds the findings audit (evidence log, reproducible) and the spec for project
one — emitting the type and space scales that generate-theme-css.ts never
learned about, resolving 18 hardcoded literals in global.css, and adding a
machine-checked parity test so the migration's core premise is verified rather
than assumed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Ten TDD tasks: parity spec first (red), then emit the type scale as Tailwind v4 composite --text-* tokens and the space scale, bring the orphaned tokens.css under the generator, ship it, and resolve global.css's 18 literals in three separately-committed categories so the one visible change is isolated. Validated the parity spec's logic against the real tokens in the real vitest runner before writing it down: 104 token leaves, 34 vars parsed today, and six spot-checked paths are value-identical, which is the premise the substrate migration rests on. Also corrects the spec: two of the five stale-literal uses are already var(--color-text-muted, #555770) fallbacks that render the token today, so the visible change is bounded to table header text, table body text, and code-block titles — not list markers and figure captions. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…e scales unemitted)
…can no longer drift
The literals #555770 and #8b8fa3 came from the old --ds-* surface and no longer match any token. Visible change, bounded to table header text, table body text, and code-block titles.
…findings Three corrections, all measured in a browser rather than reasoned about: 1. Tailwind strips the namespace prefix, so `--container-page` generates `max-w-page`, not `max-w-container-page`. The spec, the plan, and a committed code comment all had it wrong. Verified: `max-w-page` computes to 1200px, `p-section-y` to 64px, and `text-h2` to 36px/40.32px — which also confirms the `--text-*--line-height` sub-key is honoured. 2. `.shiki` and `[data-rehype-pretty-code-title]` are dead CSS. rehype-pretty-code runs with keepBackground:true, so it writes the theme background inline on the <pre> and never emits a .shiki class; no code fence uses `title=`. Zero matches on docs and blog. That narrows the visible surface of the token adoption to table header and table body text only. Recorded as findings §9; deleting dead rules is cleanup, not this project. 3. color-mix resolves and Lightning CSS emits a hex fallback plus an @supports upgrade, so the open question in the spec resolves in its favour. Also documents the website suite's 5 pre-existing failures as the baseline, so Task 10 does not read them as a regression. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…nstants var(--color-text-muted) is a light-surface role token; on the dark #1a1b26 title bar it drops to 3.6:1, below AA. Move it to --docs-code-title-fg alongside the other tokyo-night-coupled values.
… to the contract Referenced 13x across cockpit/render. It was absent from the list because the list was derived against the pre-generator tokens.css, which did not define it.
Two hand-maintained emitters of the same --ds-* namespace, from the same sources, with nothing enforcing agreement. They match today; this keeps them matching.
…t, drop an unused directive
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
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.
Why
A visual review of the docs site found real defects — both sticky rails are dead site-wide,
.docs-table-scrollnever scrolls so a props table rendersagentasag/en/ton a phone, and noscroll-marginexists so every deep link lands behind the 81px fixed nav. Roughly half the fixes cannot be written, because the components style themselves with inlinestyle={{}}objects, and inline styles cannot express:focus-visible,:hover,:last-child, or a media query.That makes a substrate migration the prerequisite. It splits into three projects; this is project 1 of 3, and it ships no user-visible feature. It exists so project 2 (802 inline style objects across 90 files) has somewhere to migrate to.
Findings audit:
docs/superpowers/audits/2026-08-29-docs-visual-review-findings.mdDesign:
docs/superpowers/specs/2026-08-29-design-token-css-var-completion-design.mdPlan:
docs/superpowers/plans/2026-08-29-design-token-css-var-completion.mdThe gap this closes
The website reads tokens from JS (
tokens.colors.accent) and from CSS (var(--color-accent)). Both derive fromlight.ts, so where a var exists the values are identical by construction. Butgenerate-theme-css.tsonly ever emitted colors, fonts, radii and shadows — so 217 of 1,188 token references had no CSS counterpart at all.colors.*/surfaces.*radius.*/shadows.*.familyvar(--font-garamond)).size/.line/.weight/.letterSpacingspace.*What changed
--text-*steps carrying--line-height/--font-weight/--letter-spacingsub-keys, so onetext-h1utility replaces four inline properties in project 2.--spacing-section-y,--spacing-section-y-tight,--spacing-container-x,--container-page.tokens.csswas hand-written, orphaned, and drifted (--ds-text-secondary: #555770vs the livergb(70,70,70)). Now generated fromlight.ts. Gains 5 names, loses none.global.css— 18 hardcoded literals resolved in three separately-committed categories, so the one visible change is isolated and revertable on its own.The one visible change
Docs table header text and body text move off a dead colour.
#555770came from the old--ds-*surface and no longer matches any token..docs-prose thrgb(85, 87, 112)rgb(115, 115, 115).docs-prose tdrgb(85, 87, 112)rgb(70, 70, 70)Both measured in a browser.
thandtddeliberately take different tokens:tdis body content and matches--tw-prose-body, whichMdxRendereralready sets tocolors.textSecondary;this an uppercase mono label and belongs with the other muted labels.Two other uses of
#555770were alreadyvar(--color-text-muted, #555770)— the var is defined, so those fallbacks were dead text. Confirmed:li::markermeasuredrgb(115,115,115)both before and after. Nothing else on any page changes.Verification
Every guard was mutation-tested — broken deliberately, confirmed red, reverted:
radius.md10px→11pxspace.sectionYclamp maxlight.probeOnlylight.probeOnly--ds-*contract--ds-canvas--ds-*contract--ds-render-greentokens.cssdriftcssVarsagreement--ds-accent→#000000Browser-measured rather than assumed:
text-h2→36pxwith40.32pxline-height (= 36 × 1.12, proving the--text-*--line-heightsub-key is honoured),p-section-y→64px,max-w-page→1200px.Also:
nx test design-tokensgreen (86),nx build website --configuration=productionsucceeds, 0 lint errors in both projects.The website vitest suite reports
5 failed | 341 passed. Those 5 are pre-existing — content assertions inPostCard,Differentiator, andthanks/pagethat drifted red because there is nonx test websitetarget so they never ran in CI. Same 5 at the baseline commit; unrelated to this work and out of scope here.Corrections made during the work
Recorded because each was a wrong belief caught by measurement:
--container-pagegeneratesmax-w-page, notmax-w-container-page— Tailwind strips the namespace prefix. The spec, the plan, and a code comment all had it wrong..shikiand[data-rehype-pretty-code-title]are dead CSS.rehype-pretty-coderuns withkeepBackground: true, so it writes the theme background inline on the<pre>and never emits a.shikiclass; no code fence usestitle=. Zero matches across docs and blog. Documented as findings §9 — deleting them is cleanup, not this project.--color-text-mutedonto the dark#1a1b26code-title bar drops contrast 5.34:1 → 3.60:1, below AA. Dead CSS today, but it contradicted the change's own rationale — that bar is coupled to the tokyo-night theme. Its foreground now lives in--docs-code-title-fgwith the other theme-coupled constants.Deliberately not done
No component
style={{}}is touched (project 2). No fix from the findings audit lands (project 3) — the sticky rails, the crushed tables, and the anchors behind the nav all stay broken. No dark theme. The cockpit apps are not wired to importtokens.css; they still render on theirvar(--ds-*, fallback)fallbacks, and changing that would flip nine example apps from dark fallbacks to light token values — its own ticket.🤖 Generated with Claude Code