Theme Catalog
render_theme_catalogView a visual catalog of all 21 themes, each card previewing colors, typography, and effects. Click to apply a theme.
Instructions
Show a visual catalog of all 21 available themes. Each card previews the theme's colors, typography, and effects. Click any card to use that theme.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Implementation Reference
- src/charts/theme-catalog.ts:1-46 (handler)The renderThemeCatalog function that executes the tool logic. It iterates over THEME_PRESETS, loads theme fonts, builds theme card HTML with palette swatches and mini bar charts, attaches a click handler to send 'Use theme' selections, and adds an HTML export button.
import { THEME_PRESETS, PALETTE_TO_CSS, loadThemeFonts, } from "../themes.js"; import type { ColorPalette, ThemePreset } from "../themes.js"; import { registerChart, escapeHtml, sendClickMessage, addHtmlExportButton } from "./shared.js"; function renderThemeCatalog(container: HTMLElement, _payload: any): void { const entries = Object.entries(THEME_PRESETS); // Load all distinct font sets const seenFonts = new Set<string>(); for (const [, theme] of entries) { const key = theme.typography.fontHeading + theme.typography.fontBody; if (!seenFonts.has(key)) { seenFonts.add(key); loadThemeFonts(theme.typography); } } const cards = entries.map(([key, theme]) => buildThemeCard(key, theme)).join(""); container.innerHTML = ` <div class="theme-catalog chart-card"> <div class="theme-catalog__header chart-card__header"> <h1 class="theme-catalog__title chart-card__title">Theme Catalog</h1> <span class="theme-catalog__subtitle">${entries.length} themes - click any card to use it</span> </div> <div class="theme-catalog__grid">${cards}</div> </div> `; addHtmlExportButton(container, "theme-catalog"); // Click handler - delegate from grid const grid = container.querySelector(".theme-catalog__grid"); if (grid) { grid.addEventListener("click", (e) => { const card = (e.target as HTMLElement).closest<HTMLElement>("[data-theme]"); if (!card) return; const name = card.dataset.theme!; sendClickMessage(`Use theme: "${name}"`); }); } } - src/charts/theme-catalog.ts:48-96 (helper)The buildThemeCard helper function that generates a single theme card's HTML, mapping palette colors to CSS variables, effect classes, swatch colors, bar chart bars, and typography/effect labels.
function buildThemeCard(key: string, theme: ThemePreset): string { // Build inline CSS variable string for scoping const vars: string[] = []; for (const [prop, cssVar] of Object.entries(PALETTE_TO_CSS)) { const value = theme.palette[prop as keyof ColorPalette]; if (value) vars.push(`${cssVar}:${value}`); } vars.push(`--font-heading:${theme.typography.fontHeading}`); vars.push(`--font-body:${theme.typography.fontBody}`); // Effect classes scoped to this card const fx: string[] = []; if (theme.effects.glowBorders) fx.push("fx-glow"); if (theme.effects.neonGlow) fx.push("fx-neon"); if (theme.effects.glassCards) fx.push("fx-glass"); // Palette swatches const swatchColors = ["--accent", "--positive", "--negative", "--c1", "--c2", "--c3", "--c4", "--c5", "--c6", "--c7"]; const swatches = swatchColors .map((c) => `<span class="tc-swatch" style="background:var(${c})"></span>`) .join(""); // CSS-only mini bar chart using palette colors const barHeights = [40, 70, 55, 85]; const barColors = ["--c1", "--c2", "--c3", "--c4"]; const bars = barHeights .map((h, i) => `<span class="tc-bar" style="height:${h}%;background:var(${barColors[i]})"></span>`) .join(""); // Typography + effects labels const typoName = theme.typography.fontHeading.split(",")[0].replace(/['"]/g, ""); const effectName = theme.effects.shimmerTitle ? "shimmer" : theme.effects.neonGlow ? "neon" : theme.effects.glowBorders ? "glow" : theme.effects.glassCards ? "glass" : theme.effects.hoverLift ? "lift" : "none"; return ` <div class="tc-card ${fx.join(" ")}" data-theme="${escapeHtml(key)}" style="${vars.join(";")}"> <div class="tc-card__bg"> <div class="tc-card__name">${escapeHtml(key)}</div> <div class="tc-card__meta">${escapeHtml(typoName)} / ${effectName}</div> <div class="tc-card__bars">${bars}</div> <div class="tc-card__swatches">${swatches}</div> </div> </div> `; } - src/charts/theme-catalog.ts:98-98 (registration)Registration of the 'render_theme_catalog' tool via registerChart('theme_catalog', 'render_theme_catalog', renderThemeCatalog). Called as a side-effect import from app.ts.
registerChart("theme_catalog", "render_theme_catalog", renderThemeCatalog); - src/themes.ts:804-941 (schema)The THEME_PRESETS data used by renderThemeCatalog — a record of all named theme presets combining palette, typography, and effects.
export const THEME_PRESETS: Record<string, ThemePreset> = { boardroom: { name: "boardroom", palette: PALETTES.boardroom, typography: TYPOGRAPHY_SETS.professional, effects: EFFECT_PRESETS.subtle, }, corporate: { name: "corporate", palette: PALETTES.corporate, typography: TYPOGRAPHY_SETS.system, effects: EFFECT_PRESETS.none, }, "sales-floor": { name: "sales-floor", palette: PALETTES["sales-floor"], typography: TYPOGRAPHY_SETS.bold, effects: EFFECT_PRESETS.energetic, }, "golden-treasury": { name: "golden-treasury", palette: PALETTES["golden-treasury"], typography: TYPOGRAPHY_SETS.luxury, effects: EFFECT_PRESETS.shimmer, }, clinical: { name: "clinical", palette: PALETTES.clinical, typography: TYPOGRAPHY_SETS.system, effects: EFFECT_PRESETS.none, }, startup: { name: "startup", palette: PALETTES.startup, typography: TYPOGRAPHY_SETS.techno, effects: EFFECT_PRESETS.energetic, }, "ops-control": { name: "ops-control", palette: PALETTES["ops-control"], typography: TYPOGRAPHY_SETS.mono, effects: EFFECT_PRESETS.energetic, }, "tokyo-midnight": { name: "tokyo-midnight", palette: PALETTES["tokyo-midnight"], typography: TYPOGRAPHY_SETS.cyberpunk, effects: EFFECT_PRESETS.neon, }, "zen-garden": { name: "zen-garden", palette: PALETTES["zen-garden"], typography: TYPOGRAPHY_SETS.editorial, effects: EFFECT_PRESETS.shimmer, }, consultant: { name: "consultant", palette: PALETTES.consultant, typography: TYPOGRAPHY_SETS.system, effects: EFFECT_PRESETS.none, }, // ── Black/AI Family ───────────────────────────────────────────────── "black-tron": { name: "black-tron", palette: PALETTES["black-tron"], typography: TYPOGRAPHY_SETS.mono, effects: EFFECT_PRESETS.neon, }, "black-elegance": { name: "black-elegance", palette: PALETTES["black-elegance"], typography: TYPOGRAPHY_SETS.professional, effects: EFFECT_PRESETS.subtle, }, "black-matrix": { name: "black-matrix", palette: PALETTES["black-matrix"], typography: TYPOGRAPHY_SETS.mono, effects: EFFECT_PRESETS.neon, }, // ── Forest Green Family ───────────────────────────────────────────── "forest-amber": { name: "forest-amber", palette: PALETTES["forest-amber"], typography: TYPOGRAPHY_SETS.professional, effects: EFFECT_PRESETS.shimmer, }, "forest-earth": { name: "forest-earth", palette: PALETTES["forest-earth"], typography: TYPOGRAPHY_SETS.editorial, effects: EFFECT_PRESETS.subtle, }, // ── Blue Sky Family ───────────────────────────────────────────────── "sky-light": { name: "sky-light", palette: PALETTES["sky-light"], typography: TYPOGRAPHY_SETS.bold, effects: EFFECT_PRESETS.none, }, "sky-ocean": { name: "sky-ocean", palette: PALETTES["sky-ocean"], typography: TYPOGRAPHY_SETS.techno, effects: EFFECT_PRESETS.energetic, }, "sky-twilight": { name: "sky-twilight", palette: PALETTES["sky-twilight"], typography: TYPOGRAPHY_SETS.cyberpunk, effects: EFFECT_PRESETS.neon, }, // ── Office/Report Family ───────────────────────────────────────────── "office-red": { name: "office-red", palette: PALETTES["office-red"], typography: TYPOGRAPHY_SETS.system, effects: EFFECT_PRESETS.none, }, // ── Gray/ML Family ────────────────────────────────────────────────── "gray-hf": { name: "gray-hf", palette: PALETTES["gray-hf"], typography: TYPOGRAPHY_SETS.system, effects: EFFECT_PRESETS.none, }, "gray-copilot": { name: "gray-copilot", palette: PALETTES["gray-copilot"], typography: TYPOGRAPHY_SETS.mono, effects: EFFECT_PRESETS.energetic, }, }; - src/themes.ts:977-1004 (helper)The PALETTE_TO_CSS mapping that translates ColorPalette keys to CSS variable names, used by buildThemeCard to generate inline styles for each theme card.
export const PALETTE_TO_CSS: Record<keyof ColorPalette, string> = { bgBase: "--bg-base", bgCard: "--bg-card", bgCard2: "--bg-card-2", bgHeader: "--bg-header", border: "--border", borderMd: "--border-md", textPrimary: "--text-primary", textSecondary: "--text-secondary", textMuted: "--text-muted", accent: "--accent", accentMuted: "--accent-muted", positive: "--positive", positiveBg: "--positive-bg", negative: "--negative", negativeBg: "--negative-bg", neutral: "--neutral", neutralBg: "--neutral-bg", c1: "--c1", c2: "--c2", c3: "--c3", c4: "--c4", c5: "--c5", c6: "--c6", c7: "--c7", shadowCard: "--shadow-card", shadowHover: "--shadow-hover", gradientStart: "--gradient-start", gradientEnd: "--gradient-end", glowColor: "--glow-color", bgGradientMid: "--bg-gradient-mid", cardGlassBg: "--card-glass-bg", };