From 7c572fbbcbf607abbf26eeea13c2a469de810c55 Mon Sep 17 00:00:00 2001 From: sb-iam <59984144+sb-iam@users.noreply.github.com> Date: Sat, 27 Jun 2026 19:39:04 -0700 Subject: [PATCH] feat(ui): re-theme Team Memory graph to match the shadcn app The app is light shadcn; GraphView was hardcoded dark-Bauhaus and clashed. Re-theme to shadcn tokens (var(--card)/--foreground/--muted-foreground/ --border, var(--primary) for active) so the panel is theme-aware (light now, follows dark mode if toggled) and native to the command-center. Node-kind encoding kept (shapes + light-readable hues); labels are sentence-case. Co-Authored-By: Claude Opus 4.8 --- docs/graph.md | 2 +- frontend/src/components/GraphView.tsx | 138 ++++++++++++++------------ 2 files changed, 73 insertions(+), 67 deletions(-) diff --git a/docs/graph.md b/docs/graph.md index c0f7956..f9c404d 100644 --- a/docs/graph.md +++ b/docs/graph.md @@ -79,7 +79,7 @@ Additive routes in `backend/src/server.ts` (shared file — additive only). - `backend/src/graph/store.ts` — `loadPodGraph`, `seedGraph`, `reachFrom` (`$graphLookup`) - `backend/src/graph/seed.ts` — `pnpm graph:seed` (writes demo into `team_model` + graph collections) - `frontend/src/lib/graph.ts` — `fetchPodGraph(podId)` -- `frontend/src/components/GraphView.tsx` — dark-Bauhaus SVG graph (toggle from `App.tsx`) +- `frontend/src/components/GraphView.tsx` — shadcn-themed SVG graph (theme-aware; toggle from `App.tsx`) ## Demo-first plan diff --git a/frontend/src/components/GraphView.tsx b/frontend/src/components/GraphView.tsx index ad2b58b..9786566 100644 --- a/frontend/src/components/GraphView.tsx +++ b/frontend/src/components/GraphView.tsx @@ -4,21 +4,31 @@ import { fetchPodGraph } from '../lib/graph.js'; type Mode = 'risk' | 'learn' | 'all'; +// Fixed, light-readable hues for the node/edge encoding (kept stable across +// light/dark so kinds stay distinguishable; the chrome uses shadcn tokens). +const BLUE = '#2563eb'; +const SLATE = '#475569'; +const SLATE_EDGE = '#94a3b8'; +const SLATE_FAINT = '#cbd5e1'; +const AMBER = '#d97706'; +const RED = '#dc2626'; +const VIOLET = '#7c3aed'; + const KIND_COLOR: Record = { - engineer: '#3B5BFF', - file: '#ECE7DA', - feature: '#F6C445', - collision: '#E2403A', - intervention: '#8b6cff', + engineer: BLUE, + file: SLATE, + feature: AMBER, + collision: RED, + intervention: VIOLET, }; const EDGE: Record = { - owns: { c: '#3B5BFF', w: 2.6 }, - editing: { c: '#ECE7DA', w: 2 }, - touches: { c: '#5d5d66', w: 1.6 }, - collides: { c: '#E2403A', w: 3.2 }, - warns: { c: '#F6C445', w: 3.2 }, - learned_from: { c: '#8b6cff', w: 2.4, dash: true }, + owns: { c: BLUE, w: 2.6 }, + editing: { c: SLATE_EDGE, w: 2 }, + touches: { c: SLATE_FAINT, w: 1.6 }, + collides: { c: RED, w: 3.2 }, + warns: { c: AMBER, w: 3.2 }, + learned_from: { c: VIOLET, w: 2.4, dash: true }, }; function NodeShape({ node }: { node: PodGraphNode }) { @@ -26,7 +36,7 @@ function NodeShape({ node }: { node: PodGraphNode }) { const { x, y } = node; switch (node.kind) { case 'engineer': - return ; + return ; case 'file': return ( = [ - { label: 'engineer', swatch: { background: '#3B5BFF' } }, - { label: 'file', swatch: { border: '2px solid #ECE7DA' } }, - { label: 'feature', swatch: { background: '#F6C445', borderRadius: '50%' } }, - { - label: 'collision', - swatch: { background: '#E2403A', clipPath: 'polygon(50% 0,100% 100%,0 100%)' }, - }, - { label: 'intervention', swatch: { background: '#8b6cff', transform: 'rotate(45deg)' } }, + { label: 'engineer', swatch: { background: BLUE } }, + { label: 'file', swatch: { border: `2px solid ${SLATE}` } }, + { label: 'feature', swatch: { background: AMBER, borderRadius: '50%' } }, + { label: 'collision', swatch: { background: RED, clipPath: 'polygon(50% 0,100% 100%,0 100%)' } }, + { label: 'intervention', swatch: { background: VIOLET, transform: 'rotate(45deg)' } }, ]; +function statusColor(status: string): string { + if (status === 'risk') return RED; + if (status === 'learned') return VIOLET; + return 'var(--foreground)'; +} + export function GraphView({ podId, onClose }: { podId: string; onClose: () => void }) { const [graph, setGraph] = useState(null); const [error, setError] = useState(null); @@ -131,40 +145,39 @@ export function GraphView({ podId, onClose }: { podId: string; onClose: () => vo return (
@@ -199,10 +212,14 @@ export function GraphView({ podId, onClose }: { podId: string; onClose: () => vo
{error && ( -

Graph error: {error}

+

+ Graph error: {error} +

)} {!graph && !error && ( -

Loading graph…

+

+ Loading graph… +

)} {graph && ( @@ -258,7 +275,7 @@ export function GraphView({ podId, onClose }: { podId: string; onClose: () => vo > - {n.label.toUpperCase()} + {n.label} ))} @@ -272,18 +289,7 @@ export function GraphView({ podId, onClose }: { podId: string; onClose: () => vo
{sel.label}
Status - - {sel.status} - + {sel.status}
Relationships @@ -296,7 +302,7 @@ export function GraphView({ podId, onClose }: { podId: string; onClose: () => vo
Continual learning
It learned
- Violet learned_from edges are ownership + The violet learned_from edges are ownership PodMan retained from accepted interventions — the graph gets sharper every session. Click any node to trace its relationships.
@@ -313,11 +319,11 @@ export function GraphView({ podId, onClose }: { podId: string; onClose: () => vo ))} - + collides - + learned_from