diff --git a/design.md b/design.md index 33c5338b73..64794e44a1 100644 --- a/design.md +++ b/design.md @@ -1,6 +1,6 @@ # OmniRoute — Design System & Visual Identity -> **Status:** standardization plan. **Phases 1–3 are implemented in this PR** (grid, primitives, status-color centralization, mono token, and the DataTable token migration). The DataTable migration is **faithful** — dark stays byte-identical (the new `--table-*` dark values equal the old hardcoded rgba); light is fixed (it was buggy always-dark via dead `var()` fallbacks). **⚠️ Wants a visual pass before merge** (light-theme tables + the secondary-text shift `#888`→`--color-text-muted`). **Phase 4 is now largely done too** (C6 focus-ring → accent, C7 Checkbox/Textarea primitives, C9 `cn()`→tailwind-merge); only the selective C8 hex-sweep remains. Note several remaining "hardcoded" hex are _intentional_ (always-dark console terminal, ReactFlow SVG strokes) and must NOT be swept. **Phase 5 (D4 + D8): the grid now reaches every standalone screen** (login/auth/error/legal/status/onboarding — their opaque `bg-bg` full-screen wrappers were hiding it) **and the dashboard content shell is fluid up to 4K** (`max-w-7xl` → `max-w-[3840px]`) so it follows the viewport on large monitors instead of centering with wide side gutters. +> **Status:** standardization plan. **Phases 1–3 are implemented in this PR** (grid, primitives, status-color centralization, mono token, and the DataTable token migration). The DataTable migration is **faithful** — dark stays byte-identical (the new `--table-*` dark values equal the old hardcoded rgba); light is fixed (it was buggy always-dark via dead `var()` fallbacks). **⚠️ Wants a visual pass before merge** (light-theme tables + the secondary-text shift `#888`→`--color-text-muted`). **Phase 4 is now largely done too** (C6 focus-ring → accent, C7 Checkbox/Textarea primitives, C9 `cn()`→tailwind-merge); only the selective C8 hex-sweep remains. Note several remaining "hardcoded" hex are _intentional_ (always-dark console terminal, ReactFlow SVG strokes) and must NOT be swept. **Phase 5 (D4 + D8): the grid now reaches every standalone screen** (login/auth/error/legal/status/onboarding — their opaque `bg-bg` full-screen wrappers were hiding it) **and the dashboard content shell is fluid up to 4K** (`max-w-7xl` → `max-w-[3840px]`) so it follows the viewport on large monitors instead of centering with wide side gutters. **Phase 6 (D9): data tables are now opaque surfaces** so the grid no longer bleeds through their rows — card-less tables paint `bg-surface`, and the two log tables' semi-transparent `bg-black/5` tint (which tailwind-merge let win over the Card's `bg-surface`) is removed. The grid size itself is already correct (32px, identical to the site); a "bigger" grid on a running instance is a stale build, not code. > **Date:** 2026-06-16 · **Scope:** unify the OmniRoute dashboard (`src/`) with the marketing site (`_mono_repo/omnirouteSite/`) into **one visual identity** — same graph-paper grid background, same color tokens, standardized components. --- @@ -192,6 +192,7 @@ Each phase: `npm run lint` + `npm run typecheck:core` + a visual pass. - **D6 — Radius 14/9 product-wide:** Rec: yes (Phase 2). - **D7 — Phase 1 ships first:** Chosen. - **D8 — Layout width (Phase 5):** the dashboard content shell was capped at `max-w-7xl` (1280px), centering with wide empty side gutters on large monitors. ✅ **DONE** — raised to a fluid `max-w-[3840px]` (true 4K): content now follows the viewport up to ~4K and only centers beyond it (`DashboardLayout.tsx`). Deliberately-narrow pages stay narrow by design (`ProviderOnboardingWizard` max-w-5xl, `Rtk`/`CavemanContextPageClient` max-w-6xl). +- **D9 — Opaque data tables (Phase 6):** with the dashboard content area now transparent (so the grid wallpaper shows through, Phase 5), data tables whose container was _not_ an opaque surface let the grid bleed through their transparent even-rows / low-alpha zebra. ✅ **DONE** — every card-less table now paints `bg-surface` (or, for the `` primitive, `background: var(--color-surface)` on its scroll container). Fixed: `DataTable` (primitive), `ProxyLogger`/`RequestLoggerV2` (their `` `bg-black/5 dark:bg-black/20` tint was winning over the Card's `bg-surface` via tailwind-merge → ~95% transparent), `BatchListTab`/`FilesListTab`/`CacheEntriesTab`/`ReasoningCacheTab`/`cache page`/`FreePoolTab`/`ModelMappingTable`/`HeaderTable`, plus the two CSS-grid "tables" in the cache views (`bg-surface/35` → `bg-surface`). Tables already inside a ``/Modal were verified opaque and deliberately left untouched (bg-surface there is a redundant no-op). The grid itself needed **no change** — dashboard `body::before` is byte-identical to the site (`--grid-size: 32px`); any "bigger grid" seen on a running instance is a stale pre-`#4143` build, not code. Guarded by `tests/unit/design-grid-background.test.ts` (Phase 6 block). --- diff --git a/src/app/(dashboard)/dashboard/batch/BatchListTab.tsx b/src/app/(dashboard)/dashboard/batch/BatchListTab.tsx index b281abae1a..860911591a 100644 --- a/src/app/(dashboard)/dashboard/batch/BatchListTab.tsx +++ b/src/app/(dashboard)/dashboard/batch/BatchListTab.tsx @@ -402,7 +402,7 @@ export default function BatchListTab({ {/* Table — 9 columns: Status | ID | Endpoint | Model | Progress | Cost | Created | Expires | Actions */} -
+
diff --git a/src/app/(dashboard)/dashboard/batch/FilesListTab.tsx b/src/app/(dashboard)/dashboard/batch/FilesListTab.tsx index 38df109db8..7c6a890510 100644 --- a/src/app/(dashboard)/dashboard/batch/FilesListTab.tsx +++ b/src/app/(dashboard)/dashboard/batch/FilesListTab.tsx @@ -162,7 +162,7 @@ export default function FilesListTab({ {/* Table */} -
+
diff --git a/src/app/(dashboard)/dashboard/cache/components/CacheEntriesTab.tsx b/src/app/(dashboard)/dashboard/cache/components/CacheEntriesTab.tsx index 0ceb58ec49..a9e93c887a 100644 --- a/src/app/(dashboard)/dashboard/cache/components/CacheEntriesTab.tsx +++ b/src/app/(dashboard)/dashboard/cache/components/CacheEntriesTab.tsx @@ -111,7 +111,7 @@ export default function CacheEntriesTab() {
{t("noEntries")}
) : ( <> -
+
diff --git a/src/app/(dashboard)/dashboard/cache/components/ReasoningCacheTab.tsx b/src/app/(dashboard)/dashboard/cache/components/ReasoningCacheTab.tsx index d87b16768b..65e9df2fcb 100644 --- a/src/app/(dashboard)/dashboard/cache/components/ReasoningCacheTab.tsx +++ b/src/app/(dashboard)/dashboard/cache/components/ReasoningCacheTab.tsx @@ -277,7 +277,7 @@ export default function ReasoningCacheTab() { {providerEntries.length > 0 && (

{t("reasoningByProvider")}

-
+
@@ -330,7 +330,7 @@ export default function ReasoningCacheTab() { {modelEntries.length > 0 && (

{t("reasoningByModel")}

-
+
@@ -376,7 +376,7 @@ export default function ReasoningCacheTab() { {t("reasoningNoData")} ) : ( -
+
{t("reasoningToolCallId")} {t("tableProvider")} diff --git a/src/app/(dashboard)/dashboard/cache/page.tsx b/src/app/(dashboard)/dashboard/cache/page.tsx index 964f56e2c9..26cf749841 100644 --- a/src/app/(dashboard)/dashboard/cache/page.tsx +++ b/src/app/(dashboard)/dashboard/cache/page.tsx @@ -293,7 +293,7 @@ function PromptTrendPanel({ />
-
+
{hourLabel} {activityLabel} @@ -570,7 +570,7 @@ export default function CachePage() {
{providerEntries.length > 0 ? ( -
+
diff --git a/src/app/(dashboard)/dashboard/settings/components/proxy/FreePoolTab.tsx b/src/app/(dashboard)/dashboard/settings/components/proxy/FreePoolTab.tsx index 8308fb6148..608959f18a 100644 --- a/src/app/(dashboard)/dashboard/settings/components/proxy/FreePoolTab.tsx +++ b/src/app/(dashboard)/dashboard/settings/components/proxy/FreePoolTab.tsx @@ -216,7 +216,7 @@ export default function FreePoolTab() { )} -
+
diff --git a/src/app/(dashboard)/dashboard/tools/agent-bridge/components/ModelMappingTable.tsx b/src/app/(dashboard)/dashboard/tools/agent-bridge/components/ModelMappingTable.tsx index a2441a4579..1750d4a7c8 100644 --- a/src/app/(dashboard)/dashboard/tools/agent-bridge/components/ModelMappingTable.tsx +++ b/src/app/(dashboard)/dashboard/tools/agent-bridge/components/ModelMappingTable.tsx @@ -48,7 +48,7 @@ export function ModelMappingTable({ agentId, mappings, onSave }: ModelMappingTab return (
-
+
diff --git a/src/app/(dashboard)/dashboard/tools/traffic-inspector/components/shared/HeaderTable.tsx b/src/app/(dashboard)/dashboard/tools/traffic-inspector/components/shared/HeaderTable.tsx index a7d660b1a3..b4939ad5bb 100644 --- a/src/app/(dashboard)/dashboard/tools/traffic-inspector/components/shared/HeaderTable.tsx +++ b/src/app/(dashboard)/dashboard/tools/traffic-inspector/components/shared/HeaderTable.tsx @@ -22,7 +22,7 @@ export function HeaderTable({ headers }: HeaderTableProps) { {masked ? "Show" : "Hide"} -
+
diff --git a/src/shared/components/DataTable.tsx b/src/shared/components/DataTable.tsx index f4f8231434..37c7369110 100644 --- a/src/shared/components/DataTable.tsx +++ b/src/shared/components/DataTable.tsx @@ -100,7 +100,16 @@ export default function DataTable({ } return ( -
+
Name
{/* Table */} - +
{loading && logs.length === 0 ? (
{t("loadingProxyLogs")}
diff --git a/src/shared/components/RequestLoggerV2.tsx b/src/shared/components/RequestLoggerV2.tsx index ee14a6527e..34166c2aa1 100644 --- a/src/shared/components/RequestLoggerV2.tsx +++ b/src/shared/components/RequestLoggerV2.tsx @@ -947,7 +947,7 @@ const RequestLoggerV2 = forwardRef
); assert.ok(!dashboardLayout.includes("max-w-7xl"), "the old 1280px max-w-7xl cap is gone"); }); + +// ── Phase 6: data tables are opaque content surfaces so the grid never bleeds through ── +// +// The dashboard content area is intentionally transparent (the body::before grid shows +// through as a wallpaper). A data table whose nearest ancestor is NOT an opaque surface +// would let the grid bleed through its transparent even-rows / low-alpha zebra rows. +// Cards already carry bg-surface; these guards cover the shared table primitives and the +// tables that render *without* a Card. Tables verified to live inside a /Modal are +// intentionally left untouched (bg-surface there would be a redundant no-op). + +test("DataTable primitive paints its own opaque surface", () => { + const dt = read("../../src/shared/components/DataTable.tsx"); + assert.ok( + dt.includes("var(--color-surface)"), + "DataTable scroll container is opaque (its even rows are transparent by design)" + ); +}); + +test("log table cards are opaque (no semi-transparent bg-black tint)", () => { + // bg-black/5|20 on a wins over the Card's own bg-surface via tailwind-merge, + // turning the big log tables ~95% transparent — the grid bled straight through them. + for (const p of [ + "../../src/shared/components/ProxyLogger.tsx", + "../../src/shared/components/RequestLoggerV2.tsx", + ]) { + const src = read(p); + assert.ok( + !src.includes("bg-black/5") && !src.includes("bg-black/20"), + `${p} must not tint the table Card with bg-black/5|20 (it drops the Card's opaque surface)` + ); + assert.ok(src.includes("bg-surface"), `${p} table card uses the opaque bg-surface`); + } +}); + +test("card-less data tables wrap their table in an opaque surface", () => { + const expect = [ + [ + "../../src/app/(dashboard)/dashboard/batch/BatchListTab.tsx", + "rounded-xl border border-[var(--color-border)] bg-[var(--color-surface)]", + ], + [ + "../../src/app/(dashboard)/dashboard/batch/FilesListTab.tsx", + "rounded-xl border border-[var(--color-border)] bg-[var(--color-surface)]", + ], + [ + "../../src/app/(dashboard)/dashboard/cache/components/CacheEntriesTab.tsx", + "overflow-x-auto bg-surface", + ], + [ + "../../src/app/(dashboard)/dashboard/settings/components/proxy/FreePoolTab.tsx", + "rounded border border-border bg-surface", + ], + [ + "../../src/app/(dashboard)/dashboard/tools/agent-bridge/components/ModelMappingTable.tsx", + "overflow-hidden bg-surface", + ], + [ + "../../src/app/(dashboard)/dashboard/tools/traffic-inspector/components/shared/HeaderTable.tsx", + "bg-surface", + ], + ]; + for (const [p, needle] of expect) { + const src = read(p); + assert.ok(src.includes(needle), `${p} must include "${needle}" so the table is opaque over the grid`); + } +}); + +test("semi-transparent cache table boxes are now opaque", () => { + for (const p of [ + "../../src/app/(dashboard)/dashboard/cache/components/ReasoningCacheTab.tsx", + "../../src/app/(dashboard)/dashboard/cache/page.tsx", + ]) { + const src = read(p); + assert.ok( + !src.includes("bg-surface/35"), + `${p} table box no longer uses the ~35%-opaque bg-surface/35 (the grid bled through it)` + ); + } +});