fix: layout overflow regression + adopt true neutral gray theme
Some checks failed
ci / build-test (push) Has been cancelled
ci / docker-build (push) Has been cancelled

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 <noreply@anthropic.com>
This commit is contained in:
2026-07-09 01:12:47 +02:00
parent cbfd09c5df
commit aa6017e0ca
2 changed files with 40 additions and 38 deletions

View File

@@ -77,7 +77,7 @@
<Toaster />
<Sidebar.Provider style="--header-height: calc(var(--spacing) * 12);">
<Sidebar.Provider class="h-svh" style="--header-height: calc(var(--spacing) * 12);">
<Sidebar.Root collapsible="icon" variant="inset">
<Sidebar.Header>
<Sidebar.Menu>
@@ -160,7 +160,7 @@
</Sidebar.Footer>
</Sidebar.Root>
<Sidebar.Inset class="h-svh min-h-0">
<Sidebar.Inset class="min-h-0 overflow-hidden">
<header class="flex h-(--header-height) shrink-0 items-center gap-1 border-b px-4 lg:gap-2 lg:px-6">
<Sidebar.Trigger class="-ms-1" />
<Separator orientation="vertical" class="mx-2 data-[orientation=vertical]:h-4" />

View File

@@ -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);