|
| 1 | +# Web / UI Architecture |
| 2 | + |
| 3 | +How the client (`packages/web`, React 18 + Vite + Tailwind + D3) is structured. |
| 4 | +This is the companion to [architecture-overview.md](./architecture-overview.md), |
| 5 | +which covers the server / graph engine / data layer. |
| 6 | + |
| 7 | +```mermaid |
| 8 | +graph TD |
| 9 | + App["App.tsx<br/>GraphProvider + ViewModeProvider"] |
| 10 | + App --> Layout["Layout<br/>sidebar · header · MobileBottomNav"] |
| 11 | + Layout --> WS["Workspace<br/>graph selector · data queries"] |
| 12 | + WS --> VM["ViewManager<br/>renders the active view mode"] |
| 13 | + WS --> Insp["NodeInspector (docked)<br/>+ on-canvas expand peek"] |
| 14 | +
|
| 15 | + VM -->|list / cards| Card["CardView"] |
| 16 | + VM -->|graph| SGV["SafeGraphVisualization<br/>→ InteractiveGraphVisualization (D3)"] |
| 17 | + VM -->|table · kanban · gantt<br/>calendar · dashboard · activity| Other["other views"] |
| 18 | +
|
| 19 | + VMC["ViewModeContext<br/>active mode + persistence"] -.-> VM |
| 20 | + VMC -.-> Layout |
| 21 | + Insp --> Modes["Card · Contents (lazy markdown) · Diagram (sub-graph)"] |
| 22 | + Audit["mobile-audit tests (CI)<br/>layout · contrast · dialogs"] -.->|gate every screen| VM |
| 23 | +``` |
| 24 | + |
| 25 | +## Pieces |
| 26 | + |
| 27 | +- **App shell** — `App.tsx` wraps the tree in `GraphProvider` (current graph + |
| 28 | + drill-in/ascend) and **`ViewModeContext`** (`contexts/ViewModeContext.tsx`), the |
| 29 | + single source of truth for the active view, persisted to `localStorage`. `Layout` |
| 30 | + draws the chrome. |
| 31 | +- **View system** — `ViewManager` renders one of 8 modes: `cards`, `graph`, |
| 32 | + `table`, `kanban`, `gantt`, `calendar`, `dashboard`, `activity`. Phones default to |
| 33 | + **`cards`** (a readable list); desktop defaults to `graph`. |
| 34 | +- **Graph** — `SafeGraphVisualization` error-boundary-wraps |
| 35 | + `InteractiveGraphVisualization`, the D3 force-directed canvas (one-shot physics, |
| 36 | + viewport culling, LOD by zoom — see `LOD_THRESHOLDS`). |
| 37 | +- **Node inspector** — a docked `NodeInspector` plus an on-canvas **expand-in-place** |
| 38 | + peek, each with a **Card / Contents / Diagram** toggle readable at any zoom |
| 39 | + (`NodeContentRenderer` lazy-loads markdown/Prism; `NodeSubgraphPreview` draws a |
| 40 | + capped static sub-graph). In-canvas card titles have a zoom-decoupled |
| 41 | + **legibility floor**. |
| 42 | + |
| 43 | +## Responsive tiers (boundary: Tailwind `md`, 768px) |
| 44 | + |
| 45 | +- **Phone (`<md`)** — `MobileBottomNav` (List / Graph / More) is the primary nav; |
| 46 | + slim chrome; the sidebar/desktop header are hidden. |
| 47 | +- **Tablet & desktop (`≥md`)** — sidebar rail + full top view-strip + all filters. |
| 48 | + |
| 49 | +## Quality gate |
| 50 | + |
| 51 | +`tests/e2e/mobile-audit.spec.ts` + `mobile-dialogs.spec.ts` run the |
| 52 | +`tests/helpers/mobileAudit.ts` auditors (sideways-scroll, squeezed labels, |
| 53 | +low-contrast/invisible text, modals clipped under the nav) across **every** screen |
| 54 | +at phone width, in CI right after the smoke gate. |
0 commit comments