Skip to content

Commit 6c0685b

Browse files
bloveclaude
andauthored
feat(design-tokens): complete the CSS-var surface so the website can leave inline styles (#845)
* docs(specs): design token CSS-var completion + docs visual review findings 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> * docs(plans): implementation plan for design token CSS-var completion 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> * test(design-tokens): assert token↔CSS-var parity (red — type and space scales unemitted) * feat(design-tokens): emit the type scale as Tailwind v4 composite text tokens * feat(design-tokens): emit the space scale; token↔CSS parity now green * test(design-tokens): pin the --ds-* names cockpit and example apps reference * refactor(design-tokens): generate tokens.css from light.ts so --ds-* can no longer drift * build(design-tokens): export and ship tokens.css alongside theme.css * refactor(website): use accent tokens for docs code chips and table rule * fix(website): docs tables and code titles use the live text tokens 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. * refactor(website): name the docs-local constants that are not design tokens * docs(design-tokens): correct the utility name and record two browser 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> * fix(website): keep the code-title foreground with the syntax-theme constants 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. * test(design-tokens): --ds-render-green is consumer-referenced, add it 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. * test(design-tokens): enforce the invariant the light.* parity exclusion assumes * test(design-tokens): assert cssVars() and generated tokens.css agree Two hand-maintained emitters of the same --ds-* namespace, from the same sources, with nothing enforcing agreement. They match today; this keeps them matching. * chore(design-tokens): align the regenerate command, fix a tint comment, drop an unused directive --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
1 parent 2d5e685 commit 6c0685b

13 files changed

Lines changed: 2378 additions & 67 deletions

apps/website/src/app/global.css

Lines changed: 45 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,35 @@
11
@import "tailwindcss";
22
@import "@threadplane/design-tokens/theme.css";
33

4+
/*
5+
* Local, non-token constants.
6+
*
7+
* These are deliberately NOT design tokens. Promoting them to
8+
* @threadplane/design-tokens would imply the design system owns the syntax
9+
* theme and the docs figure treatment. It does not.
10+
*
11+
* The --docs-code-* group is coupled to `rehypeOptions.theme` ('tokyo-night')
12+
* in components/docs/MdxRenderer.tsx. Change the shiki theme and these must
13+
* change with it.
14+
* --docs-code-title-fg is here rather than on --color-text-muted for the same
15+
* reason: it sits on a dark surface, where the light-theme muted token drops
16+
* to 3.6:1 contrast.
17+
*/
18+
:root {
19+
--docs-code-bg: #1a1b26;
20+
--docs-code-title-fg: #8b8fa3;
21+
--docs-code-border: rgba(0, 0, 0, 0.1);
22+
--docs-code-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
23+
--docs-code-title-rule: rgba(255, 255, 255, 0.06);
24+
--docs-figure-shadow: 0 4px 16px rgba(0, 32, 72, 0.1);
25+
--docs-figure-shadow-bare: 0 4px 16px rgba(0, 32, 72, 0.08);
26+
/* Accent tints in the 3.5–10% range, around --color-accent-surface (6%).
27+
* Derived rather than hardcoded so they track the accent. */
28+
--docs-accent-tint-faint: color-mix(in srgb, var(--color-accent) 3.5%, transparent);
29+
--docs-accent-tint-soft: color-mix(in srgb, var(--color-accent) 8%, transparent);
30+
--docs-accent-tint-line: color-mix(in srgb, var(--color-accent) 10%, transparent);
31+
}
32+
433
* {
534
box-sizing: border-box;
635
}
@@ -55,7 +84,7 @@ html {
5584
/* Shiki code blocks — tokyo-night theme */
5685
.shiki {
5786
padding: 1.5rem;
58-
background: #1a1b26 !important;
87+
background: var(--docs-code-bg) !important;
5988
overflow-x: auto;
6089
}
6190
.shiki code {
@@ -74,8 +103,8 @@ html {
74103
.docs-prose [data-rehype-pretty-code-figure] pre {
75104
padding: 1.25rem 1.5rem;
76105
border-radius: 0.75rem;
77-
border: 1px solid rgba(0, 0, 0, 0.1);
78-
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
106+
border: 1px solid var(--docs-code-border);
107+
box-shadow: var(--docs-code-shadow);
79108
overflow-x: auto;
80109
font-size: 0.8rem;
81110
line-height: 1.7;
@@ -97,10 +126,10 @@ html {
97126
.docs-prose [data-rehype-pretty-code-figure] [data-rehype-pretty-code-title] {
98127
font-family: var(--font-mono), monospace;
99128
font-size: 0.7rem;
100-
color: #8b8fa3;
129+
color: var(--docs-code-title-fg);
101130
padding: 0.5rem 1.5rem;
102-
background: #1a1b26;
103-
border-bottom: 1px solid rgba(255, 255, 255, 0.06);
131+
background: var(--docs-code-bg);
132+
border-bottom: 1px solid var(--docs-code-title-rule);
104133
border-radius: 0.75rem 0.75rem 0 0;
105134
}
106135

@@ -111,8 +140,8 @@ html {
111140
.docs-prose :not(pre) > code {
112141
font-family: var(--font-mono), monospace;
113142
font-size: 0.85em;
114-
background: rgba(0, 64, 144, 0.06);
115-
color: #004090;
143+
background: var(--color-accent-surface);
144+
color: var(--color-accent);
116145
padding: 0.15rem 0.4rem;
117146
border-radius: 0.25rem;
118147
font-weight: 400;
@@ -136,7 +165,7 @@ html {
136165
.docs-prose ol { list-style-type: decimal; }
137166
.docs-prose li { margin-bottom: 0.5rem; line-height: 1.6; }
138167
.docs-prose li > p { margin-bottom: 0.5rem; }
139-
.docs-prose li::marker { color: var(--color-text-muted, #555770); }
168+
.docs-prose li::marker { color: var(--color-text-muted); }
140169
.docs-prose ul ul, .docs-prose ol ol, .docs-prose ul ol, .docs-prose ol ul {
141170
margin-top: 0.5rem;
142171
margin-bottom: 0.5rem;
@@ -151,23 +180,23 @@ html {
151180
.docs-prose figure:has(> img) {
152181
margin: 2.5rem 0;
153182
padding: 0.75rem 0.75rem 0;
154-
background: rgba(0, 64, 144, 0.035);
155-
border: 1px solid rgba(0, 64, 144, 0.1);
183+
background: var(--docs-accent-tint-faint);
184+
border: 1px solid var(--docs-accent-tint-line);
156185
border-radius: 0.75rem;
157186
}
158187
.docs-prose figure:has(> img) > img {
159188
display: block;
160189
width: 100%;
161190
height: auto;
162191
border-radius: 0.5rem;
163-
box-shadow: 0 4px 16px rgba(0, 32, 72, 0.1);
192+
box-shadow: var(--docs-figure-shadow);
164193
}
165194
.docs-prose figure:has(> img) > figcaption {
166195
margin: 0;
167196
padding: 0.875rem 0.5rem 0.625rem;
168197
font-size: 0.875rem;
169198
line-height: 1.5;
170-
color: var(--color-text-muted, #555770);
199+
color: var(--color-text-muted);
171200
text-align: center;
172201
font-style: italic;
173202
}
@@ -179,7 +208,7 @@ html {
179208
height: auto;
180209
margin: 2rem auto;
181210
border-radius: 0.5rem;
182-
box-shadow: 0 4px 16px rgba(0, 32, 72, 0.08);
211+
box-shadow: var(--docs-figure-shadow-bare);
183212
}
184213

185214
/* Architecture diagrams are authored at exactly the width `.docs-prose`
@@ -192,8 +221,8 @@ html {
192221

193222
.docs-table-scroll { max-width: 100%; overflow-x: auto; margin: 1.5rem 0; }
194223
.docs-prose table { width: 100%; border-collapse: collapse; font-size: 0.875rem; margin: 0; }
195-
.docs-prose th { text-align: left; padding: 0.5rem 0.75rem; font-family: var(--font-mono); font-size: 0.75rem; text-transform: uppercase; color: #555770; border-bottom: 1px solid rgba(0, 64, 144, 0.15); }
196-
.docs-prose td { padding: 0.5rem 0.75rem; border-bottom: 1px solid rgba(0, 64, 144, 0.08); color: #555770; }
224+
.docs-prose th { text-align: left; padding: 0.5rem 0.75rem; font-family: var(--font-mono); font-size: 0.75rem; text-transform: uppercase; color: var(--color-text-muted); border-bottom: 1px solid var(--color-accent-border); }
225+
.docs-prose td { padding: 0.5rem 0.75rem; border-bottom: 1px solid var(--docs-accent-tint-soft); color: var(--color-text-secondary); }
197226
.docs-prose td code { font-size: 0.8em; }
198227

199228
/* UI primitive — Card.

0 commit comments

Comments
 (0)