Skip to content

Introduce @wafflebase/tokens shared design tokens package#292

Merged
hackerwins merged 24 commits into
mainfrom
tokens-package
May 24, 2026
Merged

Introduce @wafflebase/tokens shared design tokens package#292
hackerwins merged 24 commits into
mainfrom
tokens-package

Conversation

@hackerwins

@hackerwins hackerwins commented May 24, 2026

Copy link
Copy Markdown
Collaborator

Summary

First PR of the design-system unification roadmap (docs/design/design-system-unification.md).

  • Introduces @wafflebase/tokens as the single source of truth for the Butter & Maple palette, semantic colors, radius, and typography. TS is authoritative; a small scripts/build-css.ts emits dist/tokens.css for frontend @import.
  • Migrates the four token surfaces: frontend index.css, Sheets canvas theme, Docs canvas theme, Slides factory-default themes (default-light / default-dark) and the PPTX fallback. Canvas-only tokens (peer cursors, formula ranges, page chrome) stay local. Slides per-presentation themes are untouched at runtime — palette.neutrals.* is the factory default only.
  • Three visual extensions landed alongside the original plan and are called out in the design doc under "Extensions that landed alongside PR Update store methods for asynchronous operations #1":
    • Chrome neutralization — sidebar surface/border/foreground in semantic.ts no longer reference palette.neutrals.* (warm cream / warm dark). They now use shadcn neutral oklch so the editor reads as quiet workbench. Brand stays on primary, ring, accent, selection wash, and the active sidebar item.
    • Docs paper stays pure white in light mode and neutral dark in dark mode. Caret/text use palette.neutrals.ink; text selection wash uses butter.
    • Color picker densificationTEXT_COLORS / BG_COLORS reorganized from 20 hardcoded Material values into 32 token-aware swatches (4 intent-based rows × 8 cols × 20 px). The slides Theme row now uses PICKER_THEME_ROLES (8 main OOXML slots) so it shares its grid with the Standard row.
  • Tokens build runs first in every entry point (pnpm build, pnpm build:all, pnpm verify:fast, scripts/verify-self.mjs) so consumers never face a missing dist/.

Test plan

  • pnpm verify:fast (clean state — rm -rf packages/*/dist first)
  • pnpm verify:self (all 10 lanes green from clean state)
  • Tokens package: 16 vitest tests covering palette shape, semantic key parity, CSS emission, and WCAG AA contrast
  • WCAG smoke: foreground vs background 19:1, primary pair 4.11:1 (light) / 6.71:1 (dark), sidebar pair 15:1+
  • Browser smoke (light/dark toggle) — deferred to reviewer:
    • Document list (sidebar + header chrome — should read neutral, not cream)
    • Docs editor (caret/text warm, paper pure white, butter selection wash)
    • Sheets editor (active cell ring syrup, butter wash on multi-cell)
    • Slides editor (factory-default deck shows Butter & Maple accents; theme row + standard row align in picker)

Non-blocking limitations

  • Browser smoke deferred (captures requested at first review pass).
  • Light-mode primary contrast is 4.11:1 — clears AA-Large for chrome chips and buttons, but body text on a primary surface would need adjustment. Tracked in the lessons file for a future PR.
  • firstFamily(stack) extracted to packages/slides/src/themes/font-stack.ts and shared across the two built-in themes plus the PPTX fallback — addresses the duplication review finding.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Introduced unified design tokens package providing shared palette, semantic colors, typography, and spacing values across all apps
    • Enhanced color picker UI with refined grid layout and improved button styling
  • Documentation

    • Added design system unification roadmap and implementation guide
    • Documented tokens package architecture and integration lessons learned
  • Chores

    • Integrated tokens package into frontend, docs, sheets, and slides
    • Updated theme configurations across all apps to use shared design tokens

Review Change Stack

@coderabbitai

coderabbitai Bot commented May 24, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This PR introduces @wafflebase/tokens, a new monorepo workspace package that centralizes design tokens (Butter & Maple palette, semantic colors, radius, typography) and generates deterministic CSS variables. The tokens are migrated into frontend, docs, sheets, and slides packages, with comprehensive tests and a sequenced multi-PR design system unification roadmap.

Changes

Tokens Package Infrastructure and Core Definitions

Layer / File(s) Summary
Package Configuration & Documentation
packages/tokens/package.json, packages/tokens/tsconfig.json, packages/tokens/tsconfig.build.json, packages/tokens/README.md, docs/design/design-system-unification.md
Package metadata, ES module configuration, TypeScript build/test configuration, and comprehensive design roadmap documenting PR #1 (tokens package) and planned PR #2#9 for design system unification.
Token Definitions and Type Exports
packages/tokens/src/palette.ts, packages/tokens/src/semantic.ts, packages/tokens/src/radius.ts, packages/tokens/src/typography.ts, packages/tokens/src/index.ts
Core token constants for Butter & Maple palette (brand colors, neutrals, terminal), semantic colors (light/dark surfaces, actions, charts, sidebar), radius sizes, and typography families, with barrel exports and TypeScript type derivations.
Token Build System and Contrast Helper
packages/tokens/scripts/build-css.ts, packages/tokens/src/contrast.ts
Deterministic CSS generation script that emits :root and .dark variable blocks from TS tokens, plus WCAG-compatible hex and OKLCH color parsing and contrast ratio calculation for accessibility validation.
Token Quality & Correctness Tests
packages/tokens/test/palette.test.ts, packages/tokens/test/semantic.test.ts, packages/tokens/test/build-css.test.ts, packages/tokens/test/contrast.test.ts
Comprehensive Vitest suites validating palette/semantic/radius/typography structure, CSS variable emission, WCAG AA contrast ratios across light/dark modes, and format compliance.

Consumer Package Integration

Layer / File(s) Summary
Frontend Formatting Colors and CSS Import
packages/frontend/package.json, packages/frontend/src/index.css, packages/frontend/src/components/formatting-colors.ts
Frontend imports @wafflebase/tokens workspace dependency, adds @import @wafflebase/tokens/tokens.css`` to substitute local :root/`.dark` definitions, and migrates `TEXT_COLORS`/`BG_COLORS` formatting palettes to use `palette` token references.
Docs, Sheets, and Slides Theme Updates
packages/docs/package.json, packages/docs/src/view/theme.ts, packages/sheets/package.json, packages/sheets/src/view/theme.ts, packages/slides/package.json, packages/slides/src/themes/default-light.ts, packages/slides/src/themes/default-dark.ts, packages/slides/src/import/pptx/theme.ts, packages/slides/src/themes/font-stack.ts, packages/slides/test/import/pptx/theme.test.ts
Docs, sheets, and slides packages add @wafflebase/tokens dependency and migrate theme objects (LightTheme/DarkTheme and default presentation themes) to source colors and typography from palette and typography tokens; slides adds firstFamily utility to extract single font names from token typography stacks.
Package Dependency Declarations and Jest Configuration
packages/frontend/package.json, packages/docs/package.json, packages/sheets/package.json, packages/slides/package.json, packages/backend/package.json
All consuming packages declare @wafflebase/tokens as a workspace:* dependency; backend Jest configuration adds moduleNameMapper to resolve @wafflebase/tokens to workspace tokens/src/index.ts.

Build System and Monorepo Wiring

Layer / File(s) Summary
Root Workflow and Workspace Configuration
package.json, knip.json, scripts/verify-self.mjs
Root package.json adds tokens script and updates verify:fast and build:all to run pnpm tokens build first; knip.json registers packages/tokens workspace with entry/project globs; verify-self.mjs adds tokens:build lane at the start of the verification pipeline.

Design Planning and Color Picker Refinements

Layer / File(s) Summary
Design Roadmap and Task Documentation
docs/design/README.md, docs/tasks/README.md, docs/tasks/archive/README.md, docs/tasks/archive/2026/05/20260524-tokens-package-todo.md, docs/tasks/archive/2026/05/20260524-tokens-package-lessons.md
Adds Common table entry to design README linking design-system-unification roadmap; updates tasks index with five new active tasks; documents task archive totals; captures comprehensive implementation plan, lessons learned, WCAG contrast measurements, and follow-ups for the tokens package work.
Color Picker UI Refinements
packages/frontend/src/app/slides/themed-color-picker-helpers.ts, packages/frontend/src/app/slides/themed-color-picker.tsx, packages/frontend/src/components/color-picker-grid.tsx
Introduces PICKER_THEME_ROLES constant to display a curated 8-role subset in the theme swatch picker; updates color picker grid from 5–6 columns to 8 columns with refined button styling (rounded-sm, border-border, increased hover:scale-125).

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly Related PRs

  • wafflebase/wafflebase#179: Defines the Butter & Maple token variables (--wb-*) in packages/frontend/src/index.css that this PR migrates into the new @wafflebase/tokens package and generates deterministically.
  • wafflebase/wafflebase#35: Updates dark-mode CSS variables in packages/frontend/src/index.css :root and .dark selectors, which this PR refactors to source from the centralized tokens package instead.
  • wafflebase/wafflebase#142: Introduces or refactors the ColorPickerGrid component that this PR updates with grid column and button styling refinements.

Poem

🐰 With tokens so bright in a package brand-new,
We gathered the colors of Butter and Blue—
From Maple to Berry, from Dark mode to Light,
Each shade finds its home, and the build's done just right!
Eight columns of swatches now dance in the picker, 🎨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 23.08% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Introduce @wafflebase/tokens shared design tokens package' directly and clearly summarizes the main change: addition of a new shared design tokens package.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch tokens-package

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@hackerwins

Copy link
Copy Markdown
Collaborator Author

@copilot resolve the merge conflicts in this pull request

Copilot AI commented May 24, 2026

Copy link
Copy Markdown

@copilot resolve the merge conflicts in this pull request

Done — I merged origin/main into this PR branch and resolved the conflict in docs/tasks/README.md in commit 3cdacaf.

@github-actions

github-actions Bot commented May 24, 2026

Copy link
Copy Markdown
Contributor

Verification: verify:self

Result: ✅ PASS in 251.3s

Lane Status Duration
tokens:build ✅ pass 2.2s
sheets:build ✅ pass 14.4s
docs:build ✅ pass 12.9s
slides:build ✅ pass 14.7s
verify:fast ✅ pass 156.4s
frontend:build ✅ pass 19.5s
verify:frontend:chunks ✅ pass 0.4s
backend:build ✅ pass 5.3s
cli:build ✅ pass 2.2s
verify:entropy ✅ pass 23.3s

Verification: verify:integration

Result: ✅ PASS

@codecov

codecov Bot commented May 24, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/tokens/README.md`:
- Around line 19-21: Add a language identifier to the fenced code block
containing the command "pnpm --filter `@wafflebase/tokens` build" by changing the
opening fence to include the language (e.g., bash) so Markdownlint MD040 is
satisfied; locate the fenced block in README.md near the shown command and
update the opening triple-backtick to include the chosen language tag.

In `@packages/tokens/src/contrast.ts`:
- Around line 3-10: hexToRgb currently accepts malformed hex strings and yields
NaN channels; validate and normalize input in hexToRgb before parsing: require a
match to /^#?([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/, expand 3-character shorthand to
6 chars, then parse the six hex digits and throw a clear TypeError if the string
doesn't match or any parseInt results in NaN; apply the same
validation/normalization pattern to any other hex-to-RGB conversion used by
contrastRatio so invalid inputs consistently throw instead of producing bad
numeric results.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4d81b9d0-4221-4db0-a4a3-c82980d00af3

📥 Commits

Reviewing files that changed from the base of the PR and between 4d8dfeb and 3cdacaf.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (41)
  • docs/design/README.md
  • docs/design/design-system-unification.md
  • docs/tasks/README.md
  • docs/tasks/archive/2026/05/20260524-tokens-package-lessons.md
  • docs/tasks/archive/2026/05/20260524-tokens-package-todo.md
  • docs/tasks/archive/README.md
  • knip.json
  • package.json
  • packages/backend/package.json
  • packages/docs/package.json
  • packages/docs/src/view/theme.ts
  • packages/frontend/package.json
  • packages/frontend/src/app/slides/themed-color-picker-helpers.ts
  • packages/frontend/src/app/slides/themed-color-picker.tsx
  • packages/frontend/src/components/color-picker-grid.tsx
  • packages/frontend/src/components/formatting-colors.ts
  • packages/frontend/src/index.css
  • packages/sheets/package.json
  • packages/sheets/src/view/theme.ts
  • packages/slides/package.json
  • packages/slides/src/import/pptx/theme.ts
  • packages/slides/src/themes/default-dark.ts
  • packages/slides/src/themes/default-light.ts
  • packages/slides/src/themes/font-stack.ts
  • packages/slides/test/import/pptx/theme.test.ts
  • packages/tokens/README.md
  • packages/tokens/package.json
  • packages/tokens/scripts/build-css.ts
  • packages/tokens/src/contrast.ts
  • packages/tokens/src/index.ts
  • packages/tokens/src/palette.ts
  • packages/tokens/src/radius.ts
  • packages/tokens/src/semantic.ts
  • packages/tokens/src/typography.ts
  • packages/tokens/test/build-css.test.ts
  • packages/tokens/test/contrast.test.ts
  • packages/tokens/test/palette.test.ts
  • packages/tokens/test/semantic.test.ts
  • packages/tokens/tsconfig.build.json
  • packages/tokens/tsconfig.json
  • scripts/verify-self.mjs

Comment thread packages/tokens/README.md Outdated
Comment thread packages/tokens/src/contrast.ts
hackerwins and others added 22 commits May 25, 2026 00:29
Captures a designer-led plan to consolidate fragmented design surfaces:
shared tokens package, toolbar/popover unification, mobile parity for
Docs and Sheets, icon and type-scale tokenization. Decomposes the work
into nine sequenced PRs with explicit dependencies, risks, and a Status
table maintained as PRs land.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Locks in the 9-task TDD plan that delivers PR #1 of the design-system
unification roadmap: scaffold the tokens package, define palette /
semantic / radius / typography, generate tokens.css, add WCAG AA
contrast tests, then migrate the frontend, sheets, docs, and slides
factory-default theme. Paired lessons file captures decisions as the
work proceeds.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Introduce an empty workspace package that will hold the shared design
tokens. No consumers yet — palette and CSS generation land in the next
commits.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Mark internal as private:true and bring tsconfig in line with the
docs/slides tsconfigs (allowImportingTsExtensions, DOM.Iterable lib,
useDefineForClassFields).

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Authors the Butter & Maple palette, neutral surfaces, RGB tuples, and
the full semantic color map (light + dark) lifted from the existing
inline tokens in packages/frontend/src/index.css. Vitest covers shape
and required keys; no consumer wiring yet.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Adds renderTokensCss() + a CLI entry that writes dist/tokens.css from
the TS token sources. Output mirrors the existing :root and .dark
blocks in packages/frontend/src/index.css so the frontend can swap to
an @import in the next commit without visible diff.

Also fixes tsconfig.build.json to override allowImportingTsExtensions
so tsc can emit JS (the flag is incompatible with noEmit: false).

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Dependency-free oklch + hex parser; tests assert foreground/background
and primary pairs meet AA across both themes. Catches palette regressions
before they reach the UI.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
The original test paired butter (#F4C95D) against neutrals.dark.ink
(#FBF6EC, cream-on-dark text) which are two light colors and naturally
fail WCAG. The intent was to validate the actual UI usage: butter as a
header/chip background with dark ink text on top of it. Switching the
pair to (light.ink, butter) measures the legibility of the chip text
and passes AA_NORMAL comfortably.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Replaces the inline :root and .dark variable blocks with an import from
@wafflebase/tokens. The @theme inline mapping and @layer base rules are
unchanged. No visual change expected.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Replaces hardcoded Butter & Maple hex values (active cell ring, header
chip, selection wash, formula REFERENCE token color) with palette refs.
Canvas-only tokens like formulaRange*, peerCursor*, and search highlights
stay local — they have no shared analogue.

Also adds @wafflebase/tokens to backend Jest moduleNameMapper so the
ESM-only tokens package resolves via source when the backend test suite
loads sheets transitively.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Caret and default text color in the docs editor now use Butter & Maple
neutrals so the canvas chrome stays in tone with the surrounding shell.
Page background, ruler chrome, and the Google-blue selection wash stay
local — those are intentionally neutral.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
New presentations now ship with the Butter & Maple brand palette as the
factory default. The OOXML role mapping (dk1/lt1/accent1..6) and tint/
shade algorithm are unchanged. User-edited per-presentation themes and
PPTX imports always win at runtime.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
The factory default consumed by store/memory.ts and model/migrate.ts
when seeding new decks now reads Butter & Maple values from
@wafflebase/tokens. Ids ("default-light", "default-dark") and display
names ("Simple Light", "Simple Dark") stay stable so stored decks keep
resolving. Other built-in themes (streamline, focus, material) are
user-selectable identities and remain untouched.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Fills in the paired lessons file with measured WCAG contrasts, the
factory-default file-discovery surprise, and follow-up signals for
PR #2. The roadmap doc now uses fully qualified package paths to keep
verify:entropy doc-staleness checks green, and the Status table flips
PR #1 to "Ready to merge".

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Marks every plan step complete, then runs tasks:archive + tasks:index
so the todo/lessons files land in docs/tasks/archive/2026/05/. The
roadmap doc Status table already reflects the PR-ready state.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Two cross-package mismatches surfaced after the initial PR scope:
  - Docs text selection used Google blue while sheets cell-range wash
    used butter — same UI affordance, different tone. Switched docs
    selectionColor to butter at the existing alphas (0.30 light, 0.35
    dark) so a user selecting text in docs and selecting a cell range
    in sheets sees the same wash.
  - Docs pageBackground and rulerContentBackground used plain #ffffff /
    #2b2b2b while the brand neutrals carry a warm cream/dark-brown
    paper tone (#FFFDF7 / #241D14). Switched both to
    palette.neutrals.{light,dark}.paper so the "sheet of paper"
    surface is on-brand in both modes.

canvasBackground, rulerMarginBackground, and headerFooterBorderColor
stay neutral gray — they read as workbench chrome, not paper. They
will move into a shared canvas-surfaces semantic layer in a later PR
once a second consumer needs it.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
The slides color picker stacked a 6-col Theme grid on top of a 5-col
Standard grid with different swatch sizes — two grids that didn't
align. The 20-color TEXT_COLORS / BG_COLORS palettes also mixed
greyscale and Material accents without an obvious structure.

Unifies the layout across every consumer (slides themed picker, docs
formatting toolbar, sheets conditional format, docs table context
menu) by changing ColorPickerGrid to 6 cols and 24px swatches. The
slides Standard row matches inline. Reorganizes both TEXT_COLORS and
BG_COLORS to 18 swatches arranged as 6×3:

  Row 1  Warm neutrals (ink → paper / paper → warm tan)
  Row 2  Butter & Maple brand accents / brand-tinted highlights
  Row 3  Cool counterpoint / cool pastels

Row 2 sources Butter & Maple values directly from @wafflebase/tokens
so the Standard swatches share their warm hues with the Theme row in
the slides picker. The cool row keeps users' full color expression
even though Butter & Maple has no cool accents.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Two changes in service of a more professional office-tool feel.

Chrome neutralization
  - Sidebar surface, foreground, and border in @wafflebase/tokens
    semantic.ts no longer reference palette.neutrals.{light,dark}
    (warm Butter & Maple cream / warm dark). Swapped to the shadcn
    neutral-near-white / cool-dark defaults so the editor chrome
    reads as quiet workbench surface, not branded backdrop.
  - Docs pageBackground and rulerContentBackground reverted from
    the warm paper neutrals to pure white / neutral dark for the
    same reason. Brand presence is preserved on selection wash
    (butter), caret/text color (ink), primary buttons, focus ring,
    and the sidebar active-item.
  - palette.neutrals stays warm — it is still the right source for
    Slides factory-default themes and any marketing/landing surface.

Color picker densification
  - Picker grids unified to 8 cols × 4 rows = 32 swatches at 16×16
    px (was 6×3 = 18 at 24×24). Closer to PowerPoint / Figma
    density and visually subordinate to the editor content.
  - Slides theme row stays 6 cols (12 OOXML roles) but matches the
    16 px swatch size of the standard row, so the two grids share
    rhythm.
  - TEXT_COLORS and BG_COLORS reorganized into four semantic rows:
    neutrals → brand warm → cool counterpoint → earthy / status
    pastels.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Theme row was 6 cols × 12 OOXML slots, standard was 8 cols × 32
colors — two different grids stacked under one picker, awkward.

Introduces PICKER_THEME_ROLES (8 high-traffic OOXML roles: text,
background, accent1..6) and renders the theme row in 8 cols × 1 row.
The dropped slots (textSecondary, backgroundAlt, hyperlink,
visitedHyperlink) still exist in THEME_ROLES and resolve at runtime —
they just don't appear in the picker, since users almost never bind a
fill or text color to them explicitly.

Both grids now share rhythm. Swatch size also nudged from 16 px
(too dense for click affordance) to 20 px so buttons feel right —
matches the Google Slides picker size.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Three follow-ups raised by the branch-level code review:

[Blocking] Tokens dist is gitignored, but pnpm build / build:all /
verify:fast / verify:self all assumed it would exist before sheets/
docs/slides/frontend ran. On a fresh checkout the first downstream
build failed with TS2307. Prepended `pnpm tokens build` to the three
root scripts and added it as the first lane in scripts/verify-self.mjs
so every entry point self-bootstraps.

[Important] firstFamily(stack) was duplicated across the two built-in
slides themes and the PPTX fallback. Extracted to
packages/slides/src/themes/font-stack.ts and all three call sites now
import from there.

[Important] Three visual extensions (chrome neutralization, docs paper
revert, color picker densification) shipped alongside the original
plan but weren't reflected in the roadmap doc. Added an "Extensions
that landed alongside PR #1" subsection so a future reviewer doesn't
read the diff as scope creep.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
The rebase auto-resolution overwrote the topological build order
introduced in #287 (concurrent docs+sheets, then slides, then
concurrent frontend+backend+cli) with the simpler all-concurrent
form this branch had branched from. Restore the topological flow
and keep `pnpm tokens build` as the first step so tokens compile
before any consumer that imports them.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
CI failures
  - verify-integration and verify-browser run on fresh runners that
    don't share the verify-self artifact cache. Both build sheets/
    docs/slides directly before consumers exist, so they hit
    "Cannot find module '@wafflebase/tokens'" before reaching any
    test. Prepended `pnpm tokens build` to the
    "Build workspace packages the CLI imports at runtime" step in
    .github/workflows/ci.yml and to scripts/verify-browser-lanes.mjs.

CodeRabbit findings
  - packages/tokens/README.md: tag the build snippet as `bash` so
    Markdownlint MD040 stops warning.
  - packages/tokens/src/contrast.ts: validate the hex input shape
    before parseInt. Without the guard, `#fff` or other malformed
    inputs produce NaN channels and contrastRatio quietly returns
    a meaningless number. Added a test for the new error path.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
verify-integration failed on the rebased push: backend e2e (Jest)
loads slides/dist/node.cjs, which contains a baked-in
require('@wafflebase/tokens') from when slides was built. Jest's
moduleNameMapper only rewrites direct imports it parses — it can't
reach require() calls inside an already-compiled CJS dependency. So
the require resolved to tokens/dist/index.js (ESM with `export {}`)
and Jest choked with SyntaxError before any e2e suite started.

Add a second tsc pass that emits a CJS build to dist/cjs/, write a
dist/cjs/package.json with `"type": "commonjs"` so Node treats those
.js files as CommonJS even though the parent package is ESM, and
expose them via the `require` condition in the exports map. The ESM
build stays the default for Vite/Vitest consumers; CJS consumers
(backend Jest, anything loading slides/dist/node.cjs) now find a
matching format.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
verify-browser failed with 68 baseline mismatches on the previous
push — all driven by the intentional visual changes in this PR:

  - Sidebar surface/border switched from warm cream
    (palette.neutrals.light.bg / .rule) to shadcn neutral oklch.
  - Docs page background reverted from warm paper to pure white.
  - Color picker grids unified to 8 cols × 20 px swatches.
  - TEXT_COLORS / BG_COLORS reorganized into 4 intent-based rows
    of 8 (was 5 cols × 4 rows of 5 of hardcoded Material values).
  - Slides default-light / default-dark / PPTX fallback themes now
    use Butter & Maple palette instead of Google Material accents.

The new baselines come straight from the verify-browser actual.png
artifact on run 26365350558, so what's committed is exactly what
the Docker Playwright runner now renders.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
@hackerwins
hackerwins merged commit 8b55bfb into main May 24, 2026
4 checks passed
@hackerwins
hackerwins deleted the tokens-package branch May 24, 2026 15:59
hackerwins added a commit that referenced this pull request May 24, 2026
The Butter & Maple palette lived in four places: the frontend
@theme block in index.css, plus separate theme.ts files in sheets,
docs, and slides. Each kept its own copy of the same colors and
drifted independently — light/dark toggles produced visibly
different tones across the editor chrome and the canvas surfaces.

Land @wafflebase/tokens as the single source of truth for palette,
semantic colors, radius, and typography. TS is authoritative; a
build script emits dist/tokens.css for the frontend @import and a
parallel CJS build for compiled consumers (slides/dist/node.cjs in
backend Jest cannot interop with ESM, so the exports map publishes
both formats). Migrate the four token surfaces: frontend chrome,
Sheets canvas (active cell, header chip, selection wash, REFERENCE
token color), Docs canvas (caret/text neutrals), and Slides factory
defaults (default-light, default-dark, PPTX fallback). Canvas-only
tokens like peer cursors, formula range colors, and search
highlights stay local — they have no shared analogue. Slides
per-presentation themes are untouched at runtime; tokens act only
as the factory default.

Three visual extensions shipped alongside the plumbing because
they would have been awkward to defer once chrome was already
migrating:

  - Chrome neutralization. Sidebar surface/border/foreground in
    semantic.ts no longer reference palette.neutrals.* (warm
    cream / warm dark). Editor chrome reads as quiet workbench
    surface; brand still appears on primary, ring, accent,
    selection wash, and the active sidebar item.
  - Docs paper stays pure white. pageBackground and
    rulerContentBackground reverted to #ffffff / neutral dark.
    Caret/text use palette.neutrals.ink; selection wash uses
    butter.
  - Color picker densification. ColorPickerGrid and the slides
    ThemedColorPicker unified to 8 cols × 20 px swatches.
    TEXT_COLORS / BG_COLORS reorganized from 20 hardcoded
    Material values into 32 token-aware swatches in 4
    intent-based rows: neutrals, brand warm, cool counterpoint,
    earthy/status. Slides theme row uses PICKER_THEME_ROLES
    (the 8 high-traffic OOXML slots) so it shares a grid with
    the standard row.

Other notable bits: WCAG AA contrast smoke tests in the tokens
package (16 vitest, 4.11:1 weakest pair through 19:1); roadmap
doc docs/design/design-system-unification.md sequences this work
as PR #1 of 9; build order tightened in scripts/verify-self.mjs +
ci.yml + verify-browser-lanes.mjs so tokens build before any
downstream consumer on fresh runners; 67 visual baselines
refreshed from the verify-browser actual.png artifact to match
the intentional chrome / picker / theme changes.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
hackerwins added a commit that referenced this pull request May 24, 2026
Both tasks' work has landed on main: the Vitest migration merged as #291,
and the @wafflebase/tokens deploy fixes (publish-ghpage.yml build:all +
Dockerfile tokens build) are present on main, absorbed into #292. Their
only open todo items were trailing 'open PR / code review' process steps,
now ticked, so pnpm tasks:archive moves both to archive/2026/05 and
regenerates the index.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
@hackerwins hackerwins mentioned this pull request May 24, 2026
2 tasks
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.

2 participants