From b5211d181d77b3d6db32fc886414ff076904d486 Mon Sep 17 00:00:00 2001 From: Nicholai Date: Fri, 6 Feb 2026 22:32:21 -0700 Subject: [PATCH] feat(theme): visual theme system with presets and AI tools (#51) * feat(theme): visual theme system with presets, custom themes, and AI tools Runtime theming engine with 10 preset palettes, user custom themes persisted to D1, animated circle-reveal transitions via View Transition API, and AI agent tools for generating/editing themes incrementally. - Theme library: types, presets, CSS injection, font loading, animation - Theme provider with localStorage cache for instant load (no FOUC) - Server actions for theme CRUD and user preference persistence - Agent tools: listThemes, setTheme, generateTheme, editTheme - Appearance tab extracted from settings modal - Migration 0015: custom_themes + user_theme_preference tables - Developer documentation in docs/theme-system.md * fix(db): make migration 0016 idempotent tables were already created as 0015 before renumber. use IF NOT EXISTS so the migration is safe to re-run. --------- Co-authored-by: Nicholai --- docs/theme-system.md | 195 ++ drizzle.config.ts | 1 + drizzle/0016_noisy_gorilla_man.sql | 17 + drizzle/meta/0015_snapshot.json | 0 drizzle/meta/0016_snapshot.json | 3402 ++++++++++++++++++++ drizzle/meta/_journal.json | 7 + src/app/actions/themes.ts | 228 ++ src/app/globals.css | 24 +- src/components/settings-modal.tsx | 43 +- src/components/settings/appearance-tab.tsx | 200 ++ src/components/theme-provider.tsx | 301 +- src/db/index.ts | 2 + src/db/schema-theme.ts | 30 + src/lib/agent/chat-adapter.ts | 37 + src/lib/agent/system-prompt.ts | 101 + src/lib/agent/tools.ts | 296 ++ src/lib/theme/apply.ts | 91 + src/lib/theme/fonts.ts | 29 + src/lib/theme/index.ts | 19 + src/lib/theme/presets.ts | 1211 +++++++ src/lib/theme/transition.ts | 62 + src/lib/theme/types.ts | 89 + 22 files changed, 6323 insertions(+), 62 deletions(-) create mode 100755 docs/theme-system.md create mode 100755 drizzle/0016_noisy_gorilla_man.sql mode change 100755 => 100644 drizzle/meta/0015_snapshot.json create mode 100755 drizzle/meta/0016_snapshot.json create mode 100755 src/app/actions/themes.ts create mode 100755 src/components/settings/appearance-tab.tsx create mode 100755 src/db/schema-theme.ts create mode 100755 src/lib/theme/apply.ts create mode 100755 src/lib/theme/fonts.ts create mode 100755 src/lib/theme/index.ts create mode 100755 src/lib/theme/presets.ts create mode 100755 src/lib/theme/transition.ts create mode 100755 src/lib/theme/types.ts diff --git a/docs/theme-system.md b/docs/theme-system.md new file mode 100755 index 0000000..fdbfa55 --- /dev/null +++ b/docs/theme-system.md @@ -0,0 +1,195 @@ +Theme System +=== + +Compass ships a runtime theming engine that lets users switch between preset palettes, create custom themes through the AI agent, and edit those themes incrementally. Every theme defines light and dark color maps, typography, spacing tokens, and shadow scales. Switching themes triggers an animated circle-reveal transition from the click origin. + +This document explains how the pieces fit together, what problems the architecture solves, and where to look when something breaks. + + +How themes work +--- + +A theme is a `ThemeDefinition` object (defined in `src/lib/theme/types.ts`) containing: + +- **32 color keys** for both light and dark modes (background, foreground, primary, sidebar variants, chart colors, etc.) - all in oklch() format +- **fonts** (sans, serif, mono) as CSS font-family strings, plus an optional list of Google Font names to load at runtime +- **tokens** for border radius, spacing, letter tracking, and shadow geometry +- **shadow scales** (2xs through 2xl) for both light and dark, since some themes use colored or offset shadows +- **preview colors** (primary, background, foreground) used by the theme card swatches in settings + +When a theme is applied, `applyTheme()` in `src/lib/theme/apply.ts` builds a `