Repository navigation
chore(theme): migrate inline layout/typography CSS-var styles to Tailwind #78
Description
Background
Follow-up from a review comment on #76 (discussion) suggesting style={{ paddingInline: "var(--frame-gutter)" }} → className="px-[var(--frame-gutter)]" in Footer.tsx.
#4 only covered the theme color tokens (--color-ink, --color-paper, --color-whisper), which are wired into @theme inline in app/globals.css and auto-generate clean utilities (text-paper, bg-ink, …). The remaining inline-style CSS-var usages are all layout (--frame-*) and typography (--fs-*) tokens that currently live as plain :root custom properties — they don't generate any utilities, so they're stuck as either inline style={{}} or arbitrary-value classes.
Migrating just one site (e.g. only Footer.tsx) breaks consistency with its neighbours, which is why the suggestion was deferred. This issue tracks the broader pass.
In scope (34 sites)
paddingInline: "var(--frame-gutter)" (3)
maxWidth: "var(--frame-max)" (3)
Other --frame-* inline styles in Frame.tsx (2)
- components/ui/Frame.tsx:25 —
minHeight: "min(100svh, var(--frame-min-h-cap))" - components/ui/Frame.tsx:27 —
paddingBlock: "var(--frame-pad-y)"
fontSize: "var(--fs-*)" (28)
| File | Line | Token |
|---|---|---|
app/blog/[slug]/page.tsx |
73 | --fs-h2 |
app/blog/page.tsx |
48 | --fs-h2 |
app/blog/page.tsx |
54 | --fs-lead |
app/blog/page.tsx |
67 | --fs-body |
app/blog/page.tsx |
89 | --fs-h3 |
app/blog/page.tsx |
95 | --fs-body |
components/site/Close.tsx |
43 | --fs-body |
components/site/Close.tsx |
57 | --fs-lead |
components/site/Close.tsx |
69 | --fs-lead |
components/site/Close.tsx |
79 | --fs-lead |
components/site/Comparison.tsx |
19 | --fs-h2 |
components/site/Comparison.tsx |
29 | --fs-body |
components/site/Comparison.tsx |
68 | --fs-price |
components/site/Comparison.tsx |
88 | --fs-price |
components/site/Faq.tsx |
16 | --fs-h2 |
components/site/Footer.tsx |
14 | --fs-micro |
components/site/Hero.tsx |
20 | --fs-h1 |
components/site/Hero.tsx |
36 | --fs-body |
components/site/Hero.tsx |
52 | --fs-cta |
components/site/Hero.tsx |
64 | --fs-cta |
components/site/Hero.tsx |
74 | --fs-cta |
components/site/Method.tsx |
44 | --fs-h3 |
components/ui/ComparisonRow.tsx |
17 | --fs-body |
components/ui/FaqItem.tsx |
32 | --fs-lead |
components/ui/FaqItem.tsx |
38 | --fs-body |
components/ui/Figure.tsx |
7 | --fs-body (+ letterSpacing) |
components/ui/MethodRow.tsx |
21 | --fs-method-row (+ lineHeight) |
components/ui/MethodRow.tsx |
27 | --fs-body |
Out of scope
--reveal-delaywrites insidestyle={{}}— these set a CSS var that descendant CSS reads (animation orchestration), not a one-way styling lookup. Keep as inline style.scroll-mt-[var(--nav-h)]inFrame.tsx:23— already aclassName, not an inline style.- Color tokens — done in chore(theme): migrate remaining inline var()/style theme colors to Tailwind utilities #4 / chore(theme): migrate inline var() to Tailwind utilities (close #4) #75 / chore(theme): migrate footer to Tailwind theme utilities #76.
Approach (open question)
Two viable directions; the migration looks very different depending on which we pick:
A. Promote tokens into @theme inline with Tailwind v4 namespace names so utilities auto-generate:
--text-h1,--text-body, … (Tailwind v4--text-*namespace) →text-h1,text-body--spacing-frame-gutter,--max-width-frame, … (similar namespaces) →px-frame-gutter,max-w-frame- Pro: real utilities, no arbitrary-value classes, IDE autocomplete, doc-friendly.
- Con: renames the public CSS API; any external doc/MDX or
docs/styling referencingvar(--fs-h1)etc. needs an alias or a rename.
B. Arbitrary-value classes, keep the var names:
text-[length:var(--fs-h1)],px-[var(--frame-gutter)],max-w-[var(--frame-max)].- Pro: single PR, no token rename, no risk to external consumers.
- Con: 34 sites of bracket-soup; defeats some of chore(theme): migrate remaining inline var()/style theme colors to Tailwind utilities #4's "use real utilities" spirit.
Recommendation: A is the more lasting fix; B is reasonable if the deadline pressure is real. Either way it's one bundled PR — partial migration causes the same inconsistency that motivated this issue.
Verification
Same triple as #4:
pnpm lint && pnpm exec tsc --noEmit && pnpm buildpnpm devsmoke check: hero/h2/h3 sizes unchanged, frame gutter and max width unchanged across §01–§05 and/blog, footer micro-meta size unchanged, no layout shift at viewport breakpoints (@md,@xl,@4xl).- Optional: compare
out/_next/static/chunks/*.csssize before/after — should not balloon.
Links
- Source comment: chore(theme): migrate footer to Tailwind theme utilities #76 (comment)
- Prior color-token migration: chore(theme): migrate remaining inline var()/style theme colors to Tailwind utilities #4, chore(theme): migrate inline var() to Tailwind utilities (close #4) #75, chore(theme): migrate footer to Tailwind theme utilities #76
Metadata
Metadata
Assignees
Labels
Type
Fields
Priority
Activity
feat(blog): redesign the index and post pages as a "field-log" table (#…
chore(theme): migrate inline layout/typography CSS-var styles to Tail…
chore: theme token cleanup + chrome-active helper (#137)