Skip to content

feat: theme studio: presets, colour roles, live preview, apply to site - #562

Merged
mvilacad merged 13 commits into
mainfrom
feat/560-feat-theme-studio-theme-as-a
Oct 25, 2026
Merged

mvilacad merged 13 commits into
mainfrom
feat/560-feat-theme-studio-theme-as-a

Conversation

@mvilacad

@mvilacad mvilacad commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

Closes #560

Theme Studio

/theme/ is now a full editor on the real engine (ThemeOptions, presetContrastIssues, colorScheme), built only from lib components. Every control maps 1:1 onto a ThemeOptions key; nothing is invented by the studio.

  • Controls: Brand (colour field, 8 presets, light/dark/system, inline contrast report), Surfaces (per-scheme colour roles), Style (material picker with thumbnails drawn by the lib's own data-style CSS, recipe, elevation, paper, noise), Shape (radius, control radius, density, borders, icon stroke), Type (curated fonts with live Google Fonts load, pairs, scale, line height, weights, tracking, per-role type), Motion and button tokens.
  • Looks: 12 curated presets, search, "Surprise me" (seeded, always compiles).
  • Generate (client side, no key): text prompt to theme (EN and PT keywords, deterministic), logo or image to brand (OKLab k-means).
  • Charts follow a theme scope (lib fix, test first): chartTokens/chartPalette read from the island, ChartScope and ThemeIsland provide it; the dashboard uses the real charts.
  • Preview: 8 screens (dashboard, settings, list, sign in, landing, pricing, form, overlays) at 390/768/1280/fit, light and dark side by side. The island starts from the package defaults (designDefaults()), so it shows what a fresh app gets, not this site's sketchbook.
  • Code: theme.ts, CSS, SvelteKit and Astro wiring, share URL (#t=v1.…, round-trips), "For AI" prompt.
  • Apply to site: visitor only. Compiled CSS in the site's own key ca-site-studio, replayed by an inline script before paint, kept last in the cascade. No key means sketchbook; nothing touches the published theme, build output or lib defaults. "Reset to sketchbook" clears it.
  • Quality: undo/redo with drag coalescing, one commit per animation frame, Cmd/Ctrl+Z, controls in a Sheet below 900px, axe clean in every panel and the overlays compare state.

Lib additions

ColorField, SliderField, Slider label, @codeatlasdev/ui/utils/color (parseColorInput, contrast, wcagLevel, toHex, toOklch, extractPalette, pickBrand), designDefaults, presetContrastIssues/presetTokens/BUILTIN_PRESETS exports. Demos 988-990, docs, css-api, changeset.

tweakcn vs ours

Feature tweakcn Ours
Preset gallery, one click many community themes 12 curated looks + 8 built-in brands, search
Per-token colour editing ~30 shadcn tokens 18 roles per scheme, hex/rgb/oklch
Inline contrast checker per pair readout, in words, plus engine findings
Fonts sans/serif/mono inputs curated lists per role, live Google load, pairs
Radius / spacing / shadow sliders radius, control radius, density, border, elevation model, noise, paper
Type scale and roles letter spacing only scale, line height, weights, tracking, 6 roles
Motion, icon stroke, components no yes
Surface material no 9 materials + 15 design recipes
Preview cards, dashboard, app, marketing 8 screens, 3 widths, light/dark side by side
Undo/redo, reset, randomize yes yes (drag coalescing, Cmd+Z, seeded)
Light/dark toggle yes yes + system + compare
Code export CSS vars theme.ts, CSS, wiring for Kit and Astro
Share link yes (saved account) URL hash, no account
Apply to whole site no yes, visitor only, resettable
AI LLM prompt, image prompt and image client side, no key; "For AI" export for agents
Mobile limited Sheet, full width preview

Not matched: community theme hosting and accounts (out of scope, no backend), and real overlays inside the preview.

Static overlay replicas. The Overlays screen shows static copies of the dialog, menu and toast, drawn in place from the same classes and tokens. They are labelled "Static preview" in the UI (a notice at the top of the screen) and are not the real components: real ones open in the browser top layer, outside the themed island, and lose its tokens. Real Dialog, Menu and Toast inside a themed island needs an inline mode in the layer engine, tracked in #563. #563 blocks "tweakcn parity done": this PR does not claim parity until it lands.

Tests

  • Unit: color.test.ts, theme-studio.test.ts (state, codec, history, looks, prompt, extractCode), theme-defaults.test.ts (keeps designDefaults in lockstep with tokens.css).
  • Component: ColorField, SliderField.
  • E2E (one route, desktop, ~6 s): brand change reaches preview and code and not the page; share URL restores in a fresh context (fails when restore is removed); apply persists across navigation and resets; keyboard slider plus undo/redo. Axe spec covers all panels and overlays compare.

Also in this PR

  • stateFromRecipe(id, recipeSurface, preset) (studio-state.ts): the state of a bare design recipe, for style pages that apply a recipe to the site. Compiles to exactly designStyle(id) (test per recipe).
  • Verified in a browser at 390px: the Landing screen has no horizontal scroll, the hero title wraps in two lines, CTAs stack. Screenshots in .cache/studio/ (560-landing-390-dark.png, 560-landing-390-light.png, 560-overlays-static-390.png).

@mvilacad mvilacad changed the title feat: feat: theme studio: /theme/ as a full editor (presets, per-token colours, fonts, shape, live kit preview, share, a feat: theme studio: presets, colour roles, live preview, apply to site Oct 25, 2026
@mvilacad
mvilacad force-pushed the feat/560-feat-theme-studio-theme-as-a branch from 0167c19 to a22e1d4 Compare October 25, 2026 03:42
@mvilacad
mvilacad marked this pull request as ready for review October 25, 2026 03:42
@mvilacad
mvilacad force-pushed the feat/560-feat-theme-studio-theme-as-a branch from a22e1d4 to c0d4385 Compare October 25, 2026 06:11
Replaces the /theme/ editor with a Theme Studio built on the real engine:
looks gallery, per-scheme colour roles with contrast readouts, fonts, shape,
type roles, motion, surface picker, eight preview screens at 390/768/1280 with
a light/dark comparison, undo/redo, share URL, apply to site (visitor only),
prompt and logo generation, and an AI export prompt.

Lib: ColorField, SliderField, Slider label, public colour helpers,
designDefaults, presetContrastIssues export.
Charts read tokens from <html>, so a chart inside a data-theme-scope or
data-preset island painted the page's colors. ChartScope and ThemeIsland now
provide the island as the scope; chartTokens and chartPalette read from it.
Studio dashboard uses the real charts. Landing hero follows its frame.
@mvilacad
mvilacad force-pushed the feat/560-feat-theme-studio-theme-as-a branch from c0d4385 to bd37a5b Compare October 25, 2026 09:28
@mvilacad
mvilacad merged commit c39a426 into main Oct 25, 2026
1 check passed
@mvilacad
mvilacad deleted the feat/560-feat-theme-studio-theme-as-a branch October 25, 2026 09:33
mvilacad added a commit that referenced this pull request Oct 25, 2026
…nd / light mobile after #562 and #608 (#622)

* chore: start #612

* test: regenerate darwin baselines of /theme/ and home light mobile (#612)
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.

feat: theme studio: /theme/ as a full editor (presets, per-token colours, fonts, shape, live kit preview, share, apply to site, AI-free generation)

1 participant