diff options
| author | Fuwn <[email protected]> | 2026-01-20 00:16:14 -0800 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2026-01-20 00:16:14 -0800 |
| commit | e09fc2af31bf99698d203d0a03e78735b4d5a6b2 (patch) | |
| tree | 08b2077a70795ad518dc3b785f372190c8251c1f /internal | |
| parent | feat: Improve theme CSS mappings for comprehensive styling (diff) | |
| download | kaze-e09fc2af31bf99698d203d0a03e78735b4d5a6b2.tar.xz kaze-e09fc2af31bf99698d203d0a03e78735b4d5a6b2.zip | |
refactor: Use CSS variable overrides for proper theme integration
Instead of trying to override individual Tailwind classes (which was
fragile and incomplete), now properly override Kaze's root CSS variables
(--bg-primary, --status-ok, etc.) to use OpenCode theme values.
This works because style.css already maps all Tailwind classes to these
CSS variables, so overriding the variables automatically themes everything.
The theme flow is now:
1. OpenCode theme defines: --theme-background, --theme-success, etc.
2. Override CSS redefines: --bg-primary = var(--theme-background), etc.
3. style.css classes use: background: var(--bg-primary), etc.
This approach is much cleaner and ensures complete, consistent theming.
Diffstat (limited to 'internal')
| -rw-r--r-- | internal/server/server.go | 4 | ||||
| -rw-r--r-- | internal/theme/theme.go | 223 |
2 files changed, 49 insertions, 178 deletions
diff --git a/internal/server/server.go b/internal/server/server.go index 6d76fa0..8d491dc 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -199,8 +199,8 @@ func (s *Server) handleIndex(w http.ResponseWriter, r *http.Request) { if err != nil { s.logger.Warn("failed to load theme", "url", s.config.Site.ThemeURL, "error", err) } else if resolvedTheme != nil { - // Generate CSS variables and Tailwind mappings - cssString := resolvedTheme.GenerateCSS() + resolvedTheme.GenerateTailwindMappings() + // Generate CSS: theme variables + override Kaze's CSS variables + cssString := resolvedTheme.GenerateCSS() + resolvedTheme.GenerateVariableOverrides() themeCSS = template.CSS(cssString) } } diff --git a/internal/theme/theme.go b/internal/theme/theme.go index ac0fff9..ed10f80 100644 --- a/internal/theme/theme.go +++ b/internal/theme/theme.go @@ -183,187 +183,58 @@ func GetColorMapping() map[string]string { } } -// GenerateTailwindMappings generates CSS that maps theme variables to Tailwind classes -func (t *ResolvedTheme) GenerateTailwindMappings() string { +// GenerateVariableOverrides generates CSS that maps OpenCode theme to Kaze's CSS variables +// This is the proper approach - override the root CSS variables that style.css uses +func (t *ResolvedTheme) GenerateVariableOverrides() string { if t == nil { return "" } return ` -/* OpenCode Theme Tailwind Overrides */ - -/* ===== Page Background ===== */ -.bg-neutral-50, -.dark .bg-neutral-950 { - background-color: var(--theme-background) !important; -} - -/* ===== Panels & Cards ===== */ -/* Group headers */ -.bg-neutral-100, -.dark .bg-neutral-900 { - background-color: var(--theme-background-panel) !important; -} - -/* Badges, secondary elements */ -.bg-neutral-200, -.dark .bg-neutral-800 { - background-color: var(--theme-background-element) !important; -} - -/* ===== Text Colors ===== */ -/* Primary text */ -.text-neutral-900, -.text-neutral-950, -.dark .text-white, -.dark .text-neutral-100 { - color: var(--theme-text) !important; -} - -/* Muted/secondary text */ -.text-neutral-500, -.text-neutral-600, -.text-neutral-700, -.dark .text-neutral-400, -.dark .text-neutral-500 { - color: var(--theme-text-muted) !important; -} - -/* ===== Borders ===== */ -.border-neutral-200, -.dark .border-neutral-800 { - border-color: var(--theme-border) !important; -} - -.divide-neutral-200 > * + *, -.dark .divide-neutral-800 > * + * { - border-color: var(--theme-border) !important; -} - -/* ===== Status Colors ===== */ -/* Success/Up - status indicators and text */ -.bg-emerald-500, -.bg-emerald-500.rounded-full, -.bg-emerald-500.animate-pulse { - background-color: var(--theme-success) !important; -} - -.text-emerald-500, -.text-emerald-600, -.dark .text-emerald-400 { - color: var(--theme-success) !important; -} - -/* Status banner - success background */ -.bg-emerald-50, -.dark .bg-emerald-950\/30 { - background-color: color-mix(in srgb, var(--theme-success) 10%, transparent) !important; -} - -.border-emerald-200, -.dark .border-emerald-900 { - border-color: color-mix(in srgb, var(--theme-success) 30%, var(--theme-border)) !important; -} - -/* Warning/Degraded - status indicators and text */ -.bg-yellow-500, -.bg-yellow-500.rounded-full { - background-color: var(--theme-warning) !important; -} - -.text-yellow-500, -.text-yellow-600, -.dark .text-yellow-400 { - color: var(--theme-warning) !important; -} - -/* Status banner - warning background */ -.bg-yellow-50, -.dark .bg-yellow-950\/30 { - background-color: color-mix(in srgb, var(--theme-warning) 10%, transparent) !important; -} - -.border-yellow-200, -.dark .border-yellow-900 { - border-color: color-mix(in srgb, var(--theme-warning) 30%, var(--theme-border)) !important; -} - -/* Error/Down - status indicators and text */ -.bg-red-500, -.bg-red-500.rounded-full { - background-color: var(--theme-error) !important; -} - -.text-red-500, -.text-red-600, -.dark .text-red-400 { - color: var(--theme-error) !important; -} - -/* Status banner - error background */ -.bg-red-50, -.dark .bg-red-950\/30 { - background-color: color-mix(in srgb, var(--theme-error) 10%, transparent) !important; -} - -.border-red-200, -.dark .border-red-900 { - border-color: color-mix(in srgb, var(--theme-error) 30%, var(--theme-border)) !important; -} - -/* Unknown status */ -.bg-neutral-400.rounded-full { - background-color: var(--theme-text-muted) !important; -} - -/* ===== Interactive States ===== */ -/* Hover on group headers */ -.hover\:bg-neutral-200:hover, -.dark .hover\:bg-neutral-800:hover { - background-color: var(--theme-border) !important; -} - -/* Hover on monitor cards */ -.hover\:bg-neutral-100\/50:hover, -.dark .hover\:bg-neutral-900\/50:hover { - background-color: color-mix(in srgb, var(--theme-background-panel) 50%, transparent) !important; -} - -/* ===== SVG Icons ===== */ -.text-neutral-600.transition-transform, -.dark .text-neutral-400.transition-transform { - color: var(--theme-text-muted) !important; -} - -/* ===== Tooltip ===== */ -.tooltip { - background-color: var(--theme-background-panel) !important; - border-color: var(--theme-border) !important; - color: var(--theme-text) !important; -} - -.tooltip-header { - color: var(--theme-text) !important; -} - -.tooltip-label { - color: var(--theme-text-muted) !important; -} - -.tooltip-value { - color: var(--theme-text) !important; -} - -.tooltip-value.success { - color: var(--theme-success) !important; -} - -.tooltip-value.error { - color: var(--theme-error) !important; -} - -.tooltip-value.warning { - color: var(--theme-warning) !important; +/* OpenCode Theme - Override Kaze CSS Variables */ + +:root, :root:not(.dark) { + /* Background colors */ + --bg-primary: var(--theme-background); + --bg-secondary: var(--theme-background-panel); + --bg-tertiary: var(--theme-background-element); + + /* Border color */ + --border-color: var(--theme-border); + + /* Text colors */ + --text-primary: var(--theme-text); + --text-secondary: var(--theme-text-muted); + --text-tertiary: var(--theme-text-muted); + --text-dim: var(--theme-border); + + /* Status colors */ + --status-ok: var(--theme-success); + --status-warn: var(--theme-warning); + --status-error: var(--theme-error); + --status-unknown: var(--theme-text-muted); +} + +.dark { + /* Background colors */ + --bg-primary: var(--theme-background); + --bg-secondary: var(--theme-background-panel); + --bg-tertiary: var(--theme-background-element); + + /* Border color */ + --border-color: var(--theme-border); + + /* Text colors */ + --text-primary: var(--theme-text); + --text-secondary: var(--theme-text-muted); + --text-tertiary: var(--theme-text-muted); + --text-dim: var(--theme-border); + + /* Status colors */ + --status-ok: var(--theme-success); + --status-warn: var(--theme-warning); + --status-error: var(--theme-error); + --status-unknown: var(--theme-text-muted); } ` } |