Skip to content

WIP: theme preset gallery and custom color editor#7276

Closed
aharvard wants to merge 9 commits intomainfrom
theme-builder
Closed

WIP: theme preset gallery and custom color editor#7276
aharvard wants to merge 9 commits intomainfrom
theme-builder

Conversation

@aharvard
Copy link
Copy Markdown
Collaborator

@aharvard aharvard commented Feb 17, 2026

⚠️ This PR is a work in progress. Not ready for review yet.

Summary

Adds a full theme builder experience — preset gallery and custom color editor — on top of the token infrastructure from #7275.

Author: This work is by @spencrmartin (from #7216), integrated here with authorship preserved.

What's included

  • 10 built-in theme presets: Goose Classic, Nord, Dracula, Solarized, Monokai, GitHub, Gruvbox, Tokyo Night, One Dark, High Contrast
  • PresetGallery — grid of preset cards with tag filtering, one-click apply, color preview swatches
  • ThemeColorEditor — full-screen dialog with two tabs (Presets / Custom Colors)
  • SimpleColorPicker — hue spectrum + saturation/lightness grid, no external deps
  • ColorPreview — live preview showing how each color variable appears in real UI components (sidebar, chat bubbles, cards, buttons, etc.)
  • Custom theme CRUD — save/edit/delete custom themes to localStorage
  • "Customize Colors" button in Settings → Appearance

Key decisions

  • Zero server endpoints — everything is client-side
  • No chroma-js dependency — the color picker is self-contained
  • No page reloads — theme changes apply instantly via style.setProperty()
  • Preset merge strategy — presets define partial color overrides (~18 keys), merged on top of goose-classic defaults (~60+ keys) at apply time
  • Persistence — active theme ID and custom themes stored in localStorage

Verification

  • cargo build -p goose-server
  • cargo fmt -- --check
  • cargo clippy --all-targets -- -D warnings
  • npx tsc --noEmit (zero errors)
  • eslint (zero new errors, 1 pre-existing warning in McpAppRenderer)

Related

@aharvard aharvard changed the title feat: theme preset gallery and custom color editor WIP: theme preset gallery and custom color editor Feb 17, 2026
@aharvard aharvard force-pushed the theme-builder branch 2 times, most recently from 9bdc029 to aee1458 Compare February 17, 2026 22:08
…n.css

- Add theme-tokens.ts as single source of truth for all MCP spec token values
- Apply tokens to :root via style.setProperty() before first paint (renderer.tsx)
- Remove duplicate token values from main.css :root/.dark blocks
- main.css now only registers variable names for Tailwind (@theme inline)
  and defines app-specific aliases (sidebar, search highlight, legacy)
- Add buildMcpHostStyles() to generate light-dark() format for MCP apps
- Update ThemeContext with refreshTokens, tokenVersion, localStorage override
- Update preload and suspense-loader to use MCP-compliant variable names
Rename ~130 TSX files from legacy class names (bg-background-default,
border-default, text-muted, etc.) to MCP-compliant equivalents
(bg-background-primary, border-border-primary, text-text-secondary, etc.)

This aligns the Goose desktop UI with the MCP theming specification,
enabling consistent styling across both the host app and MCP app iframes.
Use bg-text-primary and text-background-primary to naturally invert
the color scheme inside chat bubbles, ensuring readable text in both
light and dark modes.
Section headers jumped from 5 to 7, skipping 6. This was a typo
introduced when the file was restructured into numbered sections.
- Extract shared tokens (fonts, radii, border-width) into baseTokens to
  eliminate duplication between light and dark theme definitions.
- Use type-safe Pick/Exclude to enforce the split at compile time.
- Restrict light-dark() in buildMcpHostStyles() to --color-* keys only,
  since light-dark() is a CSS color function and produces invalid values
  for non-color properties like box-shadow.
- Always wrap color keys in light-dark() for consistency, even when both
  theme values are identical (e.g. transparent, #878787).
- Add 10 built-in theme presets: Goose Classic, Nord, Dracula, Solarized,
  Monokai, GitHub, Gruvbox, Tokyo Night, One Dark, High Contrast
- Add PresetGallery with tag filtering and one-click apply
- Add ThemeColorEditor with Presets and Custom Colors tabs
- Add SimpleColorPicker (hue spectrum + saturation/lightness grid)
- Add ColorPreview showing live preview across real UI components
- Add custom theme CRUD (save/edit/delete to localStorage)
- Add "Customize Colors" button in Settings → Appearance
- Presets define partial color overrides (~18 keys), merged on top of
  goose-classic defaults (~60+ keys) at apply time
- Zero server endpoints — everything is client-side
- No external dependencies for color picking
Base automatically changed from theme-tokens to main February 23, 2026 16:41
@lifeizhou-ap
Copy link
Copy Markdown
Collaborator

Hey @aharvard 👋 Just checking in on this draft. Are you still actively working on it? If not, would you mind closing it? We can always reopen later if you pick it back up. Thanks!

@aharvard
Copy link
Copy Markdown
Collaborator Author

aharvard commented Mar 9, 2026

Thanks for checking @lifeizhou-ap, I was collaborating with @spencrmartin on this work. Yeah, we can close for now and re-open later! Thanks.

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.

3 participants