presets.ts
1 import type { DashboardTheme, ThemeTypography, ThemeLayout } from "./types"; 2 3 /** 4 * Built-in dashboard themes. 5 * 6 * Each theme defines its own palette, typography, and layout so switching 7 * themes produces visible changes beyond just color — fonts, density, and 8 * corner-radius all shift to match the theme's personality. 9 * 10 * Theme names must stay in sync with the backend's 11 * `_BUILTIN_DASHBOARD_THEMES` list in `hermes_cli/web_server.py`. 12 */ 13 14 // --------------------------------------------------------------------------- 15 // Shared typography / layout presets 16 // --------------------------------------------------------------------------- 17 18 /** Default system stack — neutral, safe fallback for every platform. */ 19 const SYSTEM_SANS = 20 'system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif'; 21 const SYSTEM_MONO = 22 'ui-monospace, "SF Mono", "Cascadia Mono", Menlo, Consolas, monospace'; 23 24 const DEFAULT_TYPOGRAPHY: ThemeTypography = { 25 fontSans: SYSTEM_SANS, 26 fontMono: SYSTEM_MONO, 27 baseSize: "15px", 28 lineHeight: "1.55", 29 letterSpacing: "0", 30 }; 31 32 const DEFAULT_LAYOUT: ThemeLayout = { 33 radius: "0.5rem", 34 density: "comfortable", 35 }; 36 37 // --------------------------------------------------------------------------- 38 // Themes 39 // --------------------------------------------------------------------------- 40 41 export const defaultTheme: DashboardTheme = { 42 name: "default", 43 label: "Hermes Teal", 44 description: "Classic dark teal — the canonical Hermes look", 45 palette: { 46 background: { hex: "#041c1c", alpha: 1 }, 47 midground: { hex: "#ffe6cb", alpha: 1 }, 48 foreground: { hex: "#ffffff", alpha: 0 }, 49 warmGlow: "rgba(255, 189, 56, 0.35)", 50 noiseOpacity: 1, 51 }, 52 typography: DEFAULT_TYPOGRAPHY, 53 layout: DEFAULT_LAYOUT, 54 }; 55 56 export const midnightTheme: DashboardTheme = { 57 name: "midnight", 58 label: "Midnight", 59 description: "Deep blue-violet with cool accents", 60 palette: { 61 background: { hex: "#0a0a1f", alpha: 1 }, 62 midground: { hex: "#d4c8ff", alpha: 1 }, 63 foreground: { hex: "#ffffff", alpha: 0 }, 64 warmGlow: "rgba(167, 139, 250, 0.32)", 65 noiseOpacity: 0.8, 66 }, 67 typography: { 68 ...DEFAULT_TYPOGRAPHY, 69 fontSans: `"Inter", ${SYSTEM_SANS}`, 70 fontMono: `"JetBrains Mono", ${SYSTEM_MONO}`, 71 fontUrl: 72 "https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;700&display=swap", 73 letterSpacing: "-0.005em", 74 }, 75 layout: { 76 ...DEFAULT_LAYOUT, 77 radius: "0.75rem", 78 }, 79 }; 80 81 export const emberTheme: DashboardTheme = { 82 name: "ember", 83 label: "Ember", 84 description: "Warm crimson and bronze — forge vibes", 85 palette: { 86 background: { hex: "#1a0a06", alpha: 1 }, 87 midground: { hex: "#ffd8b0", alpha: 1 }, 88 foreground: { hex: "#ffffff", alpha: 0 }, 89 warmGlow: "rgba(249, 115, 22, 0.38)", 90 noiseOpacity: 1, 91 }, 92 typography: { 93 ...DEFAULT_TYPOGRAPHY, 94 fontSans: `"Spectral", Georgia, "Times New Roman", serif`, 95 fontMono: `"IBM Plex Mono", ${SYSTEM_MONO}`, 96 fontUrl: 97 "https://fonts.googleapis.com/css2?family=Spectral:wght@400;500;600;700&family=IBM+Plex+Mono:wght@400;500;700&display=swap", 98 }, 99 layout: { 100 ...DEFAULT_LAYOUT, 101 radius: "0.25rem", 102 }, 103 colorOverrides: { 104 destructive: "#c92d0f", 105 warning: "#f97316", 106 }, 107 }; 108 109 export const monoTheme: DashboardTheme = { 110 name: "mono", 111 label: "Mono", 112 description: "Clean grayscale — minimal and focused", 113 palette: { 114 background: { hex: "#0e0e0e", alpha: 1 }, 115 midground: { hex: "#eaeaea", alpha: 1 }, 116 foreground: { hex: "#ffffff", alpha: 0 }, 117 warmGlow: "rgba(255, 255, 255, 0.1)", 118 noiseOpacity: 0.6, 119 }, 120 typography: { 121 ...DEFAULT_TYPOGRAPHY, 122 fontSans: `"IBM Plex Sans", ${SYSTEM_SANS}`, 123 fontMono: `"IBM Plex Mono", ${SYSTEM_MONO}`, 124 fontUrl: 125 "https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@400;500;600&family=IBM+Plex+Mono:wght@400;500&display=swap", 126 }, 127 layout: { 128 ...DEFAULT_LAYOUT, 129 radius: "0", 130 }, 131 }; 132 133 export const cyberpunkTheme: DashboardTheme = { 134 name: "cyberpunk", 135 label: "Cyberpunk", 136 description: "Neon green on black — matrix terminal", 137 palette: { 138 background: { hex: "#040608", alpha: 1 }, 139 midground: { hex: "#9bffcf", alpha: 1 }, 140 foreground: { hex: "#ffffff", alpha: 0 }, 141 warmGlow: "rgba(0, 255, 136, 0.22)", 142 noiseOpacity: 1.2, 143 }, 144 typography: { 145 ...DEFAULT_TYPOGRAPHY, 146 fontSans: `"Share Tech Mono", "JetBrains Mono", ${SYSTEM_MONO}`, 147 fontMono: `"Share Tech Mono", "JetBrains Mono", ${SYSTEM_MONO}`, 148 fontUrl: 149 "https://fonts.googleapis.com/css2?family=Share+Tech+Mono&family=JetBrains+Mono:wght@400;700&display=swap", 150 }, 151 layout: { 152 ...DEFAULT_LAYOUT, 153 radius: "0", 154 }, 155 colorOverrides: { 156 success: "#00ff88", 157 warning: "#ffd700", 158 destructive: "#ff0055", 159 }, 160 }; 161 162 export const roseTheme: DashboardTheme = { 163 name: "rose", 164 label: "Rosé", 165 description: "Soft pink and warm ivory — easy on the eyes", 166 palette: { 167 background: { hex: "#1a0f15", alpha: 1 }, 168 midground: { hex: "#ffd4e1", alpha: 1 }, 169 foreground: { hex: "#ffffff", alpha: 0 }, 170 warmGlow: "rgba(249, 168, 212, 0.3)", 171 noiseOpacity: 0.9, 172 }, 173 typography: { 174 ...DEFAULT_TYPOGRAPHY, 175 fontSans: `"Fraunces", Georgia, serif`, 176 fontMono: `"DM Mono", ${SYSTEM_MONO}`, 177 fontUrl: 178 "https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,400;9..144,500;9..144,600&family=DM+Mono:wght@400;500&display=swap", 179 }, 180 layout: { 181 ...DEFAULT_LAYOUT, 182 radius: "1rem", 183 }, 184 }; 185 186 export const BUILTIN_THEMES: Record<string, DashboardTheme> = { 187 default: defaultTheme, 188 midnight: midnightTheme, 189 ember: emberTheme, 190 mono: monoTheme, 191 cyberpunk: cyberpunkTheme, 192 rose: roseTheme, 193 };