Skip to content

feat(ui): single source of truth for design tokens (landing ↔ app sync)#208

Merged
Makisuo merged 5 commits into
mainfrom
shared-design-tokens
Jul 14, 2026
Merged

feat(ui): single source of truth for design tokens (landing ↔ app sync)#208
Makisuo merged 5 commits into
mainfrom
shared-design-tokens

Conversation

@Makisuo

@Makisuo Makisuo commented Jul 14, 2026

Copy link
Copy Markdown
Collaborator

Why

Users reported the landing page UI not matching the app. Root cause: the design tokens were hand-duplicated between apps/web/src/styles.css and apps/landing/src/styles/global.css with no shared source, and the copies had drifted:

  • --accent on landing was the amber brand color (byte-identical to --primary, a semantic mislabel) vs the app's neutral hover gray — this was actively rendering amber hover fills on the @maple/ui components landing embeds (navigation menu, command palette, sheet).
  • --chart-4: red on landing vs teal in the app (landing's red collided with --destructive/--severity-error).
  • CTAs were hand-rolled on landing while the app uses buttonVariants.
  • react-flow controls: rounded on landing vs square in the product.

What changed

  • New single source of truth: packages/ui/src/styles/tokens.css holds the full token system (:root light + .dark dark + @theme inline mapping + shared react-flow controls chrome). Both apps @import "@maple/ui/styles/tokens.css" (must come after @import "tailwindcss"); their duplicated blocks are deleted. App-local styles stay app-local (web's Sugar High/boot splash, landing's marketing tokens --bg-elevated etc.).
  • Landing stays dark-only by pinning class="dark" on <html> in Layout.astro and DocsLayout.astro; dark: utilities in shared components now render correctly there.
  • Accent semantics fixed: ~320 landing *-accent utility usages that meant "brand amber" swapped to *-primary — zero visual change (same oklch value), correct semantics. Landing's caret keyframe renamed to mcp-caret-blink to avoid colliding with the shared caret-blink from the @theme block.
  • CTA buttons unified: Hero.astro, FeatureHero.astro, and NavBar.tsx CTAs now use buttonVariants from @maple/ui (cva class strings work in .astro frontmatter). The drenched-amber bookend CTA in Quickstart.astro intentionally stays bespoke — its inverted colors sit on an amber surface.
  • Drift guard: bun run check:tokens (scripts/check-token-drift.ts) fails if either app re-declares a shared token name; wired into the CI TypeScript job.
  • DESIGN.md corrected: light primary is the shipped amber (oklch(0.66 0.16 59)), not the stale blue; added a "Token source of truth" section.

Reviewer notes

  • Landing visual deltas (intended): @maple/ui hover surfaces are now neutral instead of amber, and the trace mock's chart-4 spans render teal (matching the product) instead of red. Everything else is value-identical.
  • Landing's --destructive-foreground also moves to the app's definition (red-400 in dark) — its old copy was stale.

Verification

  • bun run check:tokens passes; verified it fails on a deliberate re-declaration.
  • turbo typecheck (web/ui + deps) passes; landing Astro build (95 pages) passes — it compiles the .astro frontmatter buttonVariants imports and resolves the new CSS export.
  • Drove both apps in the browser: landing renders dark with correct shared tokens and product-style CTAs; web app renders identically to before in both dark and light themes (token values confirmed via computed styles, screenshots in each theme).

🤖 Generated with Claude Code


Open in Devin Review

Landing and app design tokens were hand-duplicated copies that drifted:
landing's --accent was the amber brand color while the app's is a neutral
hover surface (breaking @maple/ui hover states on landing), --chart-4 was
red vs teal, CTAs were hand-rolled, and react-flow controls chrome differed.

- Move the full token system (light + dark + @theme mapping + react-flow
  controls) to packages/ui/src/styles/tokens.css; both apps import it and
  their duplicated blocks are deleted. App-local styles stay app-local.
- Landing stays dark-only by pinning class="dark" on <html> (Layout.astro
  and DocsLayout.astro).
- Swap landing's brand-amber `*-accent` utilities to `*-primary` (same
  rendered color, correct semantics; `accent` is now the neutral hover
  surface everywhere). Rename landing's caret keyframe to mcp-caret-blink
  to avoid colliding with the shared caret-blink.
- Migrate hero/feature-hero/navbar CTAs to @maple/ui buttonVariants; the
  drenched-amber bookend CTA stays bespoke on purpose.
- Add scripts/check-token-drift.ts (bun run check:tokens), wired into CI,
  failing if an app re-declares a shared token name.
- Correct DESIGN.md: light primary is amber as shipped, and document the
  token source-of-truth rule.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@pullfrog

pullfrog Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Your Pullfrog Router balance is exhausted.

You have a card on file but auto-reload is disabled, so runs paused once your balance went past the overdraft buffer.

Top up balance → · Enable auto-reload →

Pullfrog  | ⚠️ this action is pinned to a commit SHA, which freezes the cleanup step — switch to @v0 or keep the SHA fresh with Dependabot | Rerun failed job ➔View workflow run | via Pullfrog | Using Claude Opus𝕏

devin-ai-integration[bot]

This comment was marked as resolved.

… sweep

The first accent→primary sweep only matched simple utility prefixes, missing
directional borders (border-l-accent) and raw var(--accent) references in
scoped <style> blocks (the /local page components, docs index, ComparisonTable,
TraceVisualization). Under the shared tokens these resolved to the neutral
hover gray instead of brand amber. Swap them all to primary.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
devin-ai-integration[bot]

This comment was marked as resolved.

Its animation referenced the global caret-blink name, which after the token
consolidation resolves to the shared @theme keyframe (eased 70/20 rhythm)
instead of the removed 50/50 terminal blink. Define lph-caret-blink locally
in the component's scoped style, mirroring how docs/index.astro handles it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Users flagged the landing app examples as feeling fake / not matching the
app. Rebuilt the hero AppMock against screenshots of the live product so
every view uses the app's actual chrome and semantics:

- Sidebar mirrors the app: org switcher (avatar + Organization sublabel),
  real nav order and grouping (Overview/Services/Service Map · Traces/Logs/
  Metrics/Replays/Infrastructure · Errors/Alerts), user footer.
- Topbar with collapse toggle, per-tab breadcrumb (CSS :has()-driven), and
  the amber Connect button.
- Page headers use the product pattern: display title + muted subtitle and
  outlined toolbar buttons (production selector, Last N hours, Reload).
- Severity tokens replace raw palette colors everywhere: INFO is green
  (severity-info) not blue, status chips 200/500 use severity tokens,
  method chips are blue GET / amber POST like the trace list.
- Services view rebuilt to the real table: amber names + namespace subline,
  P50/P95/P99, red error-rate sparklines, env group header chip, filter
  rail with counts.
- Traces view: two-line root span (method chip + path + timestamp), service
  chips with +N, underlined amber trace IDs, real filter rail (Duration
  p50/p95, Has Error, Root Traces Only, Environment, Namespace),
  "Showing 100 traces" footer.
- Logs view: search + severity-dot filters with counts, stacked
  info/warn/error histogram, chevron + dot + colored level rows.
- Overview: All clear alert strip, Services/Healthy/Degraded/Unhealthy
  health band, uppercase stat cards with vs-prev deltas, chart legends.
- Service map: COLOR BY / Re-sort canvas chips, zoom controls, edge label
  chips (~calls err%), ~-prefixed rates, brand-colored REDIS/POSTGRES
  badges, product footer (hints + service legend + health legend).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
At the mock's scaled-down size the "~calls err%" chips render oversized
relative to the nodes and crowd the links; the graph reads better bare.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@Makisuo Makisuo merged commit 65d2287 into main Jul 14, 2026
6 of 8 checks passed
@Makisuo Makisuo deleted the shared-design-tokens branch July 14, 2026 17:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant