From 841886f6d5421578a76362bcccec5286c3f75707 Mon Sep 17 00:00:00 2001 From: RaymondVerhoef Date: Wed, 15 Jul 2026 21:58:32 +0200 Subject: [PATCH] feat: add full-screen toggle to knowledge graph view Admin graph view was cramped inside the sidebar-constrained content area, making it hard to inspect and edit larger graphs. Adds a full-screen overlay toggle (button + Esc to exit) that expands the graph/table view and edit panels to fill the viewport. Co-Authored-By: Claude Sonnet 5 --- src/components/admin/KnowledgeGraph.jsx | 36 ++++++++++++++++++++----- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/src/components/admin/KnowledgeGraph.jsx b/src/components/admin/KnowledgeGraph.jsx index a0c3e25..2e093ec 100644 --- a/src/components/admin/KnowledgeGraph.jsx +++ b/src/components/admin/KnowledgeGraph.jsx @@ -3,7 +3,7 @@ import * as d3 from 'd3'; import * as db from '../../lib/db'; import { callLLM } from '../../lib/llm'; import { EMIT_GRAPH_ACTIONS_TOOL } from '../../lib/llmTools'; -import { Network, Table2 } from 'lucide-react'; +import { Network, Table2, Maximize2, Minimize2 } from 'lucide-react'; import { useGraphData } from '../../hooks/useGraphData'; import { filterAiActions } from '../../lib/graphGuard'; import GraphControls from './graph/GraphControls'; @@ -87,6 +87,7 @@ const KnowledgeGraph = () => { const [analyzeNotice, setAnalyzeNotice] = useState(null); // info-level message from last analyze const [isRestoring, setIsRestoring] = useState(false); const [viewMode, setViewMode] = useState('graph'); // 'graph' | 'table' + const [isFullscreen, setIsFullscreen] = useState(false); const { topics, relations, snapshotMeta, @@ -96,15 +97,29 @@ const KnowledgeGraph = () => { // ── Canvas sizing ──────────────────────────────────────────────────────────── useEffect(() => { - if (!wrapperRef.current) return; const measure = () => { + if (!wrapperRef.current) return; const { width, height } = wrapperRef.current.getBoundingClientRect(); - setDimensions({ width, height }); + if (width > 0 && height > 0) setDimensions({ width, height }); }; - measure(); + // rAF: toggling view mode / fullscreen resizes the wrapper without firing a + // window resize event, so re-measure once the DOM has reflowed. + const raf = requestAnimationFrame(measure); window.addEventListener('resize', measure); - return () => window.removeEventListener('resize', measure); - }, []); + return () => { + cancelAnimationFrame(raf); + window.removeEventListener('resize', measure); + }; + }, [viewMode, isFullscreen]); + + // ── Esc exits fullscreen ───────────────────────────────────────────────────── + + useEffect(() => { + if (!isFullscreen) return; + const onKey = (e) => { if (e.key === 'Escape') setIsFullscreen(false); }; + window.addEventListener('keydown', onKey); + return () => window.removeEventListener('keydown', onKey); + }, [isFullscreen]); // ── D3 force graph ─────────────────────────────────────────────────────────── @@ -433,7 +448,7 @@ const KnowledgeGraph = () => { // ── Render ─────────────────────────────────────────────────────────────────── return ( -
+
{/* Main view: graph canvas or table */}
{/* View-mode toggle */} @@ -456,6 +471,13 @@ const KnowledgeGraph = () => { > Table +
{viewMode === 'graph' ? (