From aa6017e0ca79745fa6984c83617d73455f0690d6 Mon Sep 17 00:00:00 2001 From: dtoro Date: Thu, 9 Jul 2026 01:12:47 +0200 Subject: [PATCH] fix: layout overflow regression + adopt true neutral gray theme MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: two issues surfaced after the dashboard-01 shell change (cbfd09c). (1) Sidebar.Inset previously had an explicit h-svh that hard-capped the app's height at the viewport; adding variant="inset" put a margin on that same fixed-height box, pushing it taller than the viewport with nothing left in the chain to cap it (Sidebar.Provider's own wrapper only sets min-h-svh — a floor, not a ceiling). Result: the whole page scrolled as one long document instead of each page's own content scrolling internally with the header pinned — confirmed via computed styles, e.g. Entities.svelte's table wrapper measured scrollHeight 6531px against a 900px viewport, all of it spilling past body instead of scrolling in its own rounded-border container. (2) The color palette was GitHub-dark-inspired (blue-tinted grays: #0d1117 bg, #58a6ff primary/accent) rather than the neutral grays the shadcn-svelte dashboard-01 reference actually uses. Change: - App.svelte: moved the height cap up to Sidebar.Provider itself (class="h-svh") instead of Sidebar.Inset, since the cap needs to sit above wherever the inset variant's margin gets applied, not on the same box as the margin. - app.css: replaced the core tokens (background/foreground/card/ popover/primary/secondary/muted/accent/border/input/ring/sidebar-*) with shadcn's canonical dark-theme OKLCH values (0-chroma neutral grays), pulled directly from huntabyte/shadcn-svelte's own docs/src/app.css rather than approximated. --success/--warning deliberately kept as real, distinguishable colors — they signal actual health state, and desaturating them to match the neutral chrome would reintroduce the "can't tell what's actually happening" problem this whole project started from (see 279549c). --accent-blue now aliases --sidebar-primary (still a real blue) instead of --primary, so the couple of spots wanting an interactive "pop" still have one while buttons/links/focus rings ride the neutral --primary. Risk: reversible_low (UI-only). Verification: npx tsc --noEmit clean (excluding pre-existing unrelated .svelte type-resolution warnings). go build/vet clean (backend untouched, sanity check only). Manually verified in the browser preview at 1400px: document.body.scrollHeight now exactly matches window.innerHeight on both Overview and the 193-row Entities table (previously 6531px vs 900px); scrolled the Entities table wrapper to row ~60 and confirmed the header/filter bar/column headers stay pinned while only the table body scrolls; confirmed neutral gray rendering across Overview's stat cards, the event-rate chart, and Chat's tool-call list. Co-Authored-By: Claude Sonnet 5 --- web/src/App.svelte | 4 +-- web/src/app.css | 74 ++++++++++++++++++++++++---------------------- 2 files changed, 40 insertions(+), 38 deletions(-) diff --git a/web/src/App.svelte b/web/src/App.svelte index a8a866d..00e6678 100644 --- a/web/src/App.svelte +++ b/web/src/App.svelte @@ -77,7 +77,7 @@ - + @@ -160,7 +160,7 @@ - +
diff --git a/web/src/app.css b/web/src/app.css index 56f9152..8480042 100644 --- a/web/src/app.css +++ b/web/src/app.css @@ -2,59 +2,61 @@ @custom-variant dark (&:is(.dark *)); +/* Neutral gray theme matching shadcn/ui's canonical dark palette (0-chroma + OKLCH grays) — the app is dark-only, so :root carries the dark values + directly rather than gating behind a .dark class. --success/--warning are + Oikos-specific semantic status colors (real health state), kept + distinguishable rather than desaturated to match the neutral chrome. */ :root { - --radius: 0.5rem; - --background: #0d1117; - --foreground: #e6edf3; - --card: #161b22; - --card-foreground: #e6edf3; - --popover: #161b22; - --popover-foreground: #e6edf3; - --primary: #58a6ff; - --primary-foreground: #0d1117; - --secondary: #21262d; - --secondary-foreground: #e6edf3; - --muted: #21262d; - --muted-foreground: #8b949e; - --accent: #292e36; - --accent-foreground: #e6edf3; - --destructive: #f85149; - --destructive-foreground: #ffffff; + --radius: 0.625rem; + --background: oklch(0.145 0 0); + --foreground: oklch(0.985 0 0); + --card: oklch(0.205 0 0); + --card-foreground: oklch(0.985 0 0); + --popover: oklch(0.205 0 0); + --popover-foreground: oklch(0.985 0 0); + --primary: oklch(0.922 0 0); + --primary-foreground: oklch(0.205 0 0); + --secondary: oklch(0.269 0 0); + --secondary-foreground: oklch(0.985 0 0); + --muted: oklch(0.269 0 0); + --muted-foreground: oklch(0.708 0 0); + --accent: oklch(0.371 0 0); + --accent-foreground: oklch(0.985 0 0); + --destructive: oklch(0.704 0.191 22.216); + --destructive-foreground: oklch(0.985 0 0); --success: #3fb950; --warning: #d29922; - --border: #30363d; - --input: #30363d; - --ring: #58a6ff; - --sidebar: #161b22; - --sidebar-foreground: #e6edf3; - --sidebar-primary: #58a6ff; - --sidebar-primary-foreground: #0d1117; - --sidebar-accent: #21262d; - --sidebar-accent-foreground: #e6edf3; - --sidebar-border: #30363d; - --sidebar-ring: #58a6ff; + --border: oklch(1 0 0 / 10%); + --input: oklch(1 0 0 / 15%); + --ring: oklch(0.556 0 0); + --sidebar: oklch(0.205 0 0); + --sidebar-foreground: oklch(0.985 0 0); + --sidebar-primary: oklch(0.488 0.243 264.376); + --sidebar-primary-foreground: oklch(0.985 0 0); + --sidebar-accent: oklch(0.269 0 0); + --sidebar-accent-foreground: oklch(0.985 0 0); + --sidebar-border: oklch(1 0 0 / 10%); + --sidebar-ring: oklch(0.439 0 0); --font-mono: 'SF Mono', 'Fira Code', 'Cascadia Code', monospace; /* legacy aliases still referenced by Chat/Sessions/App */ --bg: var(--background); --bg-surface: var(--card); - --bg-deeper: #0a0e13; + --bg-deeper: oklch(0.11 0 0); --bg-hover: var(--secondary); --bg-active: var(--accent); --text: var(--foreground); --text-muted: var(--muted-foreground); - --accent-blue: var(--primary); + /* accent-blue stays a real blue (matches --sidebar-primary) for the few + spots that want an interactive "pop" — everything else (buttons, + links, focus rings) rides the neutral --primary now. */ + --accent-blue: var(--sidebar-primary); --accent-green: var(--success); --accent-red: var(--destructive); --accent-orange: var(--warning); } -/* the app is dark-only; treat root as the dark theme unconditionally */ -.dark { - --background: #0d1117; - --foreground: #e6edf3; -} - @theme inline { --radius-sm: calc(var(--radius) - 4px); --radius-md: calc(var(--radius) - 2px);