From 4533f8aa38edce825441acdac7df752bce66ae43 Mon Sep 17 00:00:00 2001 From: Christoph Brandau Date: Sun, 23 Aug 2026 23:38:42 +0200 Subject: [PATCH] style(theme): add dialog & panel CSS vars and refactor status panel styles Add CSS custom properties for dialog backdrop, shadows, and panel highlights to centralize visual theming. Refactor the status panel overlay to consume these tokens and use color-mix instead of hardcoded rgba values. This improves visual consistency and lets overlays adapt cleanly to appearance changes and theme variants. - Centralize dialog and panel visuals with new CSS variables - Replace fixed rgba values with tokenized colors and color-mix - Move borders, shadows, and gradients to use the new theme tokens --- src/App.svelte | 6 ++++- src/lib/components/StatusPanel.svelte | 39 +++++++++++++++------------ 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/src/App.svelte b/src/App.svelte index d110032..fc95917 100644 --- a/src/App.svelte +++ b/src/App.svelte @@ -1179,7 +1179,8 @@ root.dataset.appearance = next; const customProperties = [ "--app-bg", "--app-button-bg", "--app-input-bg", "--app-dialog-bg", "--app-dialog-chrome", - "--app-settings-row-bg", "--color-surface", "--color-surface-alt", "--color-surface-dim", + "--app-dialog-backdrop", "--app-dialog-shadow", "--app-panel-shadow", "--app-settings-row-bg", + "--color-surface", "--color-surface-alt", "--color-surface-dim", "--color-surface-hover", "--color-surface-raised", "--color-surface-solid", "--color-border", "--color-border-subtle", "--color-border-input", "--color-primary", "--color-primary-dark", "--color-accent", "--color-ink", "--color-ink-muted", "--color-ink-faint", "--color-ink-dim", @@ -1195,6 +1196,9 @@ "--app-input-bg": `color-mix(in srgb, ${surface} 88%, white)`, "--app-dialog-bg": surface, "--app-dialog-chrome": `color-mix(in srgb, ${surface} 90%, ${background})`, + "--app-dialog-backdrop": `color-mix(in srgb, ${background} 72%, transparent)`, + "--app-dialog-shadow": `0 24px 68px color-mix(in srgb, ${text} 24%, transparent), 0 2px 12px color-mix(in srgb, ${text} 12%, transparent)`, + "--app-panel-shadow": `0 18px 48px color-mix(in srgb, ${text} 18%, transparent), inset 0 1px 0 color-mix(in srgb, ${surface} 88%, white)`, "--app-settings-row-bg": `color-mix(in srgb, ${surface} 92%, ${background})`, "--color-surface": surface, "--color-surface-alt": `color-mix(in srgb, ${surface} 82%, ${background})`, diff --git a/src/lib/components/StatusPanel.svelte b/src/lib/components/StatusPanel.svelte index 7bea36c..8b56e6e 100644 --- a/src/lib/components/StatusPanel.svelte +++ b/src/lib/components/StatusPanel.svelte @@ -660,8 +660,12 @@ display: grid; place-items: center; background: - radial-gradient(circle at 50% 38%, rgba(111, 140, 255, 0.1), transparent 55%), - rgba(7, 10, 16, 0.62); + radial-gradient( + circle at 50% 38%, + color-mix(in srgb, var(--color-accent) 13%, transparent), + transparent 55% + ), + var(--app-dialog-backdrop); backdrop-filter: blur(4px); animation: status-panel-overlay-in 120ms ease; } @@ -673,13 +677,13 @@ gap: 12px; width: min(300px, calc(100% - 32px)); padding: 26px 28px 26px; - border: 1px solid rgba(90, 111, 154, 0.28); + border: 1px solid var(--color-border-input); border-radius: 16px; background: - linear-gradient(180deg, rgba(23, 29, 43, 0.92), rgba(12, 17, 27, 0.94)), - var(--color-surface-raised); + var(--app-panel-highlight), + var(--app-dialog-bg); color: var(--color-ink); - box-shadow: 0 18px 44px rgba(0, 0, 0, 0.34), inset 0 1px 0 rgba(255, 255, 255, 0.05); + box-shadow: var(--app-dialog-shadow); } .status-panel-overlay-mark { @@ -694,7 +698,7 @@ .status-panel-overlay-halo { position: absolute; inset: 6px; - border: 1px solid rgba(111, 140, 255, 0.22); + border: 1px solid color-mix(in srgb, var(--color-primary) 34%, transparent); border-radius: 22px; transform: rotate(45deg); } @@ -703,7 +707,7 @@ } .status-panel-overlay-halo.halo-two { inset: 16px; - border-color: rgba(77, 182, 214, 0.24); + border-color: color-mix(in srgb, var(--color-accent) 38%, transparent); animation: status-panel-overlay-halo-breathe 2.4s ease-in-out infinite reverse; } @@ -721,16 +725,16 @@ stroke-linecap: round; stroke-dasharray: 165; stroke-dashoffset: 165; - filter: drop-shadow(0 0 6px rgba(77, 182, 214, 0.32)); + filter: drop-shadow(0 0 6px color-mix(in srgb, var(--color-accent) 38%, transparent)); animation: status-panel-overlay-trace-draw 2.6s ease-in-out infinite; } - .status-panel-overlay-traces .trace-main { stroke: #6f8cff; } + .status-panel-overlay-traces .trace-main { stroke: var(--color-primary); } .status-panel-overlay-traces .trace-branch { - stroke: #4db6d6; + stroke: var(--color-accent); animation-delay: 0.28s; } .status-panel-overlay-traces .trace-cut { - stroke: rgba(177, 186, 208, 0.42); + stroke: color-mix(in srgb, var(--color-ink-muted) 52%, transparent); stroke-dasharray: 128; stroke-dashoffset: 128; animation-delay: 0.55s; @@ -743,8 +747,8 @@ height: 64px; object-fit: contain; filter: - drop-shadow(0 8px 12px rgba(0, 0, 0, 0.5)) - drop-shadow(0 0 10px rgba(77, 182, 214, 0.2)); + drop-shadow(0 8px 12px color-mix(in srgb, var(--color-ink) 24%, transparent)) + drop-shadow(0 0 10px color-mix(in srgb, var(--color-accent) 24%, transparent)); animation: status-panel-overlay-icon-float 2.4s ease-in-out infinite; } @@ -765,15 +769,16 @@ height: 4px; overflow: hidden; border-radius: 999px; - background: rgba(111, 140, 255, 0.14); + border: 1px solid var(--color-border-subtle); + background: color-mix(in srgb, var(--color-primary) 12%, var(--color-surface-dim)); } .status-panel-overlay-bar span { position: absolute; inset: 0; width: 46%; border-radius: inherit; - background: linear-gradient(90deg, transparent, #6f8cff 40%, #4db6d6 74%, transparent); - box-shadow: 0 0 12px rgba(77, 182, 214, 0.26); + background: linear-gradient(90deg, transparent, var(--color-primary) 40%, var(--color-accent) 74%, transparent); + box-shadow: 0 0 12px color-mix(in srgb, var(--color-accent) 32%, transparent); animation: status-panel-overlay-bar-slide 1.35s ease-in-out infinite; }