Skip to content

chore(theme): promote --frame-* layout tokens to Tailwind namespaces #102

Closed

Description

@yigitdot

Background

Follow-up from a review comment on #101 (gemini-code-assist, medium): #101 (closing #78) migrated the typography tokens to Tailwind v4's --text-* namespace (Approach A — real text-h1, text-body, … utilities), but kept the layout --frame-* tokens as raw vars consumed via arbitrary-value classes (Approach B — px-[var(--frame-gutter)], max-w-[var(--frame-max)], …), matching the existing scroll-mt-[var(--nav-h)] precedent. This was a deliberate split (see #78's "Approach (open question)" section). This issue tracks the remaining "Approach A for layout" option, should we want it.

Proposal

Promote the layout tokens in app/globals.css's @theme inline block to Tailwind v4 namespaces so standard utilities auto-generate (no bracket-soup):

  • --frame-gutter: clamp(1.5rem, 4vw, 4rem) → --spacing-frame-gutter ⇒ px-frame-gutter
  • --frame-pad-y: clamp(5rem, 9vw, 7rem) → --spacing-frame-pad-y ⇒ py-frame-pad-y
  • --frame-max: 1280px → --container-frame ⇒ max-w-frame (also yields a @frame container-query variant — harmless)
  • --frame-min-h-cap: 54rem → fold the min() into the token: --spacing-frame-min-h: min(100svh, 54rem) ⇒ min-h-frame-min-h (alternatively keep --frame-min-h-cap as a raw var and leave min-h-[min(100svh,var(--frame-min-h-cap))] as-is — it's irreducibly an arbitrary value otherwise)

Sites to update

  • components/ui/Frame.tsx — px-frame-gutter py-frame-pad-y min-h-frame-min-h on the <section>, max-w-frame on the inner <div>
  • components/site/Footer.tsx — px-frame-gutter, max-w-frame
  • components/site/Chrome.tsx — px-frame-gutter, max-w-frame
  • app/globals.css — the lone CSS ref right: var(--frame-gutter) (mobile-menu close button) → var(--spacing-frame-gutter); update the --frame-* mentions in the :root --nav-h comment and the @theme inline comments

Trade-off

Renames the public CSS-var API (--frame-* → --spacing-frame-* / --container-frame). No external consumers were found when #78 was scoped (docs/, content/blog/, all .css/.ts(x) — app/globals.css is the website's only stylesheet), so this is low-risk; bundle as one PR (a partial migration reintroduces the inconsistency #78 fixed).

Verification

Same triple as #78: pnpm lint && pnpm exec tsc --noEmit && pnpm test && pnpm build; pnpm dev smoke (frame gutter / max-width rail / min-height unchanged across §01–§05, /blog, a post); confirm out/_next/static/chunks/*.css is roughly flat in size.

Links

Activity

  1. github-actions commented on May 13, 2026

    @github-actions

    🎯 Agentic Issue Triage

    This is a well-scoped follow-up chore to promote the remaining --frame-* layout tokens into Tailwind v4 namespaces — the "Approach A for layout" left on the table after #101 closed #78. Low risk, no external consumers, clear acceptance criteria.

    📋 Summary & Context

    Type: Refactor / chore (CSS token migration)
    Complexity: Low–medium — mechanical rename across ~4 files
    Risk: Low — app/globals.css is the sole stylesheet; no external consumers confirmed in #78's scope

    This is the layout half of the migration that #101 only partially completed (typography tokens were promoted, layout tokens were kept as arbitrary-value classes). This issue proposes finishing the job by renaming tokens into Tailwind v4 namespaces so real utility classes are generated.

    Affected files:

    • app/globals.css — rename tokens in @theme inline, update the lone right: var(--frame-gutter) raw CSS ref and comments
    • components/ui/Frame.tsx — replace arbitrary-value classes
    • components/site/Footer.tsx — replace arbitrary-value classes
    • components/site/Chrome.tsx — replace arbitrary-value classes
    🔧 Implementation checklist
    • In app/globals.css @theme inline:
      • --frame-gutter → --spacing-frame-gutter
      • --frame-pad-y → --spacing-frame-pad-y
      • --frame-max → --container-frame
      • --frame-min-h-cap → --spacing-frame-min-h: min(100svh, 54rem) (or leave as raw var — see trade-off note in issue)
    • Update the lone raw CSS ref: right: var(--frame-gutter) → right: var(--spacing-frame-gutter) (mobile-menu close button)
    • Update --frame-* mentions in :root comments and @theme inline comments
    • Frame.tsx: replace px-[var(--frame-gutter)], py-[var(--frame-pad-y)], min-h-[...], max-w-[var(--frame-max)] with new utility classes
    • Footer.tsx: replace px-[var(--frame-gutter)], max-w-[var(--frame-max)]
    • Chrome.tsx: replace px-[var(--frame-gutter)], max-w-[var(--frame-max)]
    • Run verification: pnpm lint && pnpm exec tsc --noEmit && pnpm test && pnpm build
    • Smoke-test pnpm dev — confirm gutter/max-width/min-height are visually unchanged across §01–§05, /blog, and a post
    • (Optional) Compare out/_next/static/chunks/*.css size before/after
    ⚠️ Trade-off to decide before starting

    The --frame-min-h-cap token is used as min-h-[min(100svh,var(--frame-min-h-cap))] — this expression is irreducibly an arbitrary value unless the min() computation is folded into the token itself. The issue proposes --spacing-frame-min-h: min(100svh, 54rem) → min-h-frame-min-h, which works but bakes in the 100svh constraint at the token level. Decide upfront whether to fold or leave this one as Approach B.

    🔗 Related issues & resources

    Generated by Agentic Triage for issue #102 · ● 1.3M · ◷

    To install this agentic workflow, run

    gh aw add githubnext/agentics/workflows/issue-triage.md@c7d030cd6d4607b90d9ac3ffc8b24aff4f251632
    
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions