From 6963733764e92868662d00108d20888b23e76b43 Mon Sep 17 00:00:00 2001 From: Pedram Amini Date: Tue, 30 Dec 2025 12:57:59 -0600 Subject: [PATCH 01/10] MAESTRO: Remove Document Graph button from file panel header Part of mind map refactor: Document Graph is now only accessible via: - Right-click context menu on markdown files ("Focus in Graph") - File preview panel action button Removed: - GitGraph icon button from FileExplorerPanel header - onOpenGraphView prop from FileExplorerPanel interface - isGraphViewOpen and onOpenGraphView props from RightPanel interface - Corresponding prop passing in App.tsx --- src/renderer/App.tsx | 2 -- src/renderer/components/FileExplorerPanel.tsx | 15 ++------------- src/renderer/components/RightPanel.tsx | 9 +-------- 3 files changed, 3 insertions(+), 23 deletions(-) diff --git a/src/renderer/App.tsx b/src/renderer/App.tsx index 219f4590..49a7e0c6 100644 --- a/src/renderer/App.tsx +++ b/src/renderer/App.tsx @@ -9736,8 +9736,6 @@ function MaestroConsoleInner() { console.error('[onFileClick] Failed to read file:', error); } }} - isGraphViewOpen={isGraphViewOpen} - onOpenGraphView={() => setIsGraphViewOpen(true)} onFocusFileInGraph={(relativePath: string) => { setGraphFocusFilePath(relativePath); setIsGraphViewOpen(true); diff --git a/src/renderer/components/FileExplorerPanel.tsx b/src/renderer/components/FileExplorerPanel.tsx index 007b1ecf..898a18f2 100644 --- a/src/renderer/components/FileExplorerPanel.tsx +++ b/src/renderer/components/FileExplorerPanel.tsx @@ -1,7 +1,7 @@ import React, { useEffect, useRef, useState, useCallback, useMemo, memo } from 'react'; import { createPortal } from 'react-dom'; import { useVirtualizer } from '@tanstack/react-virtual'; -import { ChevronRight, ChevronDown, ChevronUp, Folder, RefreshCw, Check, Eye, EyeOff, GitGraph, Target, Copy, ExternalLink, Server } from 'lucide-react'; +import { ChevronRight, ChevronDown, ChevronUp, Folder, RefreshCw, Check, Eye, EyeOff, Target, Copy, ExternalLink, Server } from 'lucide-react'; import type { Session, Theme, FocusArea } from '../types'; import type { FileNode } from '../types/fileTree'; import type { FileTreeChanges } from '../utils/fileExplorer'; @@ -62,7 +62,6 @@ interface FileExplorerPanelProps { onShowFlash?: (message: string) => void; showHiddenFiles: boolean; setShowHiddenFiles: (value: boolean) => void; - onOpenGraphView?: () => void; /** Callback to open graph view focused on a specific file (relative path to session.cwd) */ onFocusFileInGraph?: (relativePath: string) => void; } @@ -73,7 +72,7 @@ function FileExplorerPanelInner(props: FileExplorerPanelProps) { filteredFileTree, selectedFileIndex, setSelectedFileIndex, activeFocus, activeRightTab, previewFile, setActiveFocus, fileTreeFilterInputRef, toggleFolder, handleFileClick, expandAllFolders, collapseAllFolders, updateSessionWorkingDirectory, refreshFileTree, setSessions, onAutoRefreshChange, onShowFlash, - showHiddenFiles, setShowHiddenFiles, onOpenGraphView, onFocusFileInGraph + showHiddenFiles, setShowHiddenFiles, onFocusFileInGraph } = props; const { registerLayer, unregisterLayer, updateLayerHandler } = useLayerStack(); @@ -480,16 +479,6 @@ function FileExplorerPanelInner(props: FileExplorerPanelProps) { >{session.cwd}
- {onOpenGraphView && ( - - )}
From ac0ae0ac73c13b4b97cb26e475a8ad72a7dcbd67 Mon Sep 17 00:00:00 2001 From: Pedram Amini Date: Tue, 30 Dec 2025 13:03:52 -0600 Subject: [PATCH 02/10] MAESTRO: Remove documentGraphLayoutMode setting from useSettings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Part of the Document Graph → Mind Map refactoring effort. The layout mode setting is being removed in preparation for the new deterministic mind map layout that won't need a force/hierarchical toggle. Changes: - Remove documentGraphLayoutMode from UseSettingsReturn interface - Remove state, setter, and loading logic in useSettings.ts - Remove props passed to DocumentGraphView in App.tsx - Remove "Default Layout Mode" toggle from SettingsModal.tsx - Update CLAUDE.md to remove layoutMode from settings documentation --- CLAUDE.md | 1 - src/renderer/App.tsx | 3 -- src/renderer/components/SettingsModal.tsx | 50 ---------------------- src/renderer/hooks/settings/useSettings.ts | 20 --------- 4 files changed, 74 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index ce34dc32..24d0e621 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -846,7 +846,6 @@ const LOAD_MORE_INCREMENT = 25; ```typescript // In useSettings.ts -documentGraphLayoutMode: 'force' | 'hierarchical' // Saved layout preference documentGraphShowExternalLinks: boolean // Show external link nodes (default: false) documentGraphMaxNodes: number // Initial pagination limit (50-1000, default: 200) ``` diff --git a/src/renderer/App.tsx b/src/renderer/App.tsx index 49a7e0c6..5bd75465 100644 --- a/src/renderer/App.tsx +++ b/src/renderer/App.tsx @@ -329,7 +329,6 @@ function MaestroConsoleInner() { defaultStatsTimeRange, documentGraphShowExternalLinks, documentGraphMaxNodes, - documentGraphLayoutMode, } = settings; @@ -8795,8 +8794,6 @@ function MaestroConsoleInner() { }} focusFilePath={graphFocusFilePath} onFocusFileConsumed={() => setGraphFocusFilePath(undefined)} - savedLayoutMode={documentGraphLayoutMode} - onLayoutModeChange={settings.setDocumentGraphLayoutMode} defaultShowExternalLinks={documentGraphShowExternalLinks} onExternalLinksChange={settings.setDocumentGraphShowExternalLinks} defaultMaxNodes={documentGraphMaxNodes} diff --git a/src/renderer/components/SettingsModal.tsx b/src/renderer/components/SettingsModal.tsx index a7a3afea..dad7ea1f 100644 --- a/src/renderer/components/SettingsModal.tsx +++ b/src/renderer/components/SettingsModal.tsx @@ -238,8 +238,6 @@ export const SettingsModal = memo(function SettingsModal(props: SettingsModalPro setDocumentGraphShowExternalLinks, documentGraphMaxNodes, setDocumentGraphMaxNodes, - documentGraphLayoutMode, - setDocumentGraphLayoutMode, // Stats settings statsCollectionEnabled, setStatsCollectionEnabled, @@ -1594,54 +1592,6 @@ export const SettingsModal = memo(function SettingsModal(props: SettingsModalPro className="p-3 rounded border space-y-3" style={{ borderColor: theme.colors.border, backgroundColor: theme.colors.bgMain }} > - {/* Default Layout Mode */} -
- -
- - -
-

- Layout algorithm used when opening the Document Graph. -

-
- {/* Show External Links */}
diff --git a/src/renderer/hooks/settings/useSettings.ts b/src/renderer/hooks/settings/useSettings.ts index 0aca7244..4c3ee8fc 100644 --- a/src/renderer/hooks/settings/useSettings.ts +++ b/src/renderer/hooks/settings/useSettings.ts @@ -284,8 +284,6 @@ export interface UseSettingsReturn { setColorBlindMode: (value: boolean) => void; // Document Graph settings - documentGraphLayoutMode: 'force' | 'hierarchical'; - setDocumentGraphLayoutMode: (value: 'force' | 'hierarchical') => void; documentGraphShowExternalLinks: boolean; setDocumentGraphShowExternalLinks: (value: boolean) => void; documentGraphMaxNodes: number; @@ -412,7 +410,6 @@ export function useSettings(): UseSettingsReturn { const [colorBlindMode, setColorBlindModeState] = useState(false); // Document Graph settings - const [documentGraphLayoutMode, setDocumentGraphLayoutModeState] = useState<'force' | 'hierarchical'>('force'); const [documentGraphShowExternalLinks, setDocumentGraphShowExternalLinksState] = useState(false); // Default: false const [documentGraphMaxNodes, setDocumentGraphMaxNodesState] = useState(200); // Default: 200 @@ -1105,12 +1102,6 @@ export function useSettings(): UseSettingsReturn { window.maestro.settings.set('colorBlindMode', value); }, []); - // Document Graph layout mode - const setDocumentGraphLayoutMode = useCallback((value: 'force' | 'hierarchical') => { - setDocumentGraphLayoutModeState(value); - window.maestro.settings.set('documentGraphLayoutMode', value); - }, []); - // Document Graph show external links const setDocumentGraphShowExternalLinks = useCallback((value: boolean) => { setDocumentGraphShowExternalLinksState(value); @@ -1202,7 +1193,6 @@ export function useSettings(): UseSettingsReturn { const savedContextManagementSettings = await window.maestro.settings.get('contextManagementSettings'); const savedKeyboardMasteryStats = await window.maestro.settings.get('keyboardMasteryStats'); const savedColorBlindMode = await window.maestro.settings.get('colorBlindMode'); - const savedDocumentGraphLayoutMode = await window.maestro.settings.get('documentGraphLayoutMode'); const savedDocumentGraphShowExternalLinks = await window.maestro.settings.get('documentGraphShowExternalLinks'); const savedDocumentGraphMaxNodes = await window.maestro.settings.get('documentGraphMaxNodes'); const savedStatsCollectionEnabled = await window.maestro.settings.get('statsCollectionEnabled'); @@ -1431,12 +1421,6 @@ export function useSettings(): UseSettingsReturn { if (savedColorBlindMode !== undefined) setColorBlindModeState(savedColorBlindMode as boolean); // Document Graph settings - if (savedDocumentGraphLayoutMode !== undefined) { - const validModes = ['force', 'hierarchical']; - if (validModes.includes(savedDocumentGraphLayoutMode as string)) { - setDocumentGraphLayoutModeState(savedDocumentGraphLayoutMode as 'force' | 'hierarchical'); - } - } if (savedDocumentGraphShowExternalLinks !== undefined) { setDocumentGraphShowExternalLinksState(savedDocumentGraphShowExternalLinks as boolean); } @@ -1603,8 +1587,6 @@ export function useSettings(): UseSettingsReturn { getUnacknowledgedKeyboardMasteryLevel, colorBlindMode, setColorBlindMode, - documentGraphLayoutMode, - setDocumentGraphLayoutMode, documentGraphShowExternalLinks, setDocumentGraphShowExternalLinks, documentGraphMaxNodes, @@ -1734,8 +1716,6 @@ export function useSettings(): UseSettingsReturn { getUnacknowledgedKeyboardMasteryLevel, colorBlindMode, setColorBlindMode, - documentGraphLayoutMode, - setDocumentGraphLayoutMode, documentGraphShowExternalLinks, setDocumentGraphShowExternalLinks, documentGraphMaxNodes, From af64e313f4e8b5dfe1612d229f3b99414291de7c Mon Sep 17 00:00:00 2001 From: Pedram Amini Date: Tue, 30 Dec 2025 13:07:17 -0600 Subject: [PATCH 03/10] MAESTRO: Remove physics settings from Document Graph - Remove Settings2 and RotateCcw imports from lucide-react - Remove ForcePhysicsSettings and DEFAULT_PHYSICS imports from ForceGraph - Remove showPhysicsPanel and physics state variables - Remove the entire Physics Settings button and dropdown panel UI - Remove physics prop from ForceGraph component (uses internal DEFAULT_PHYSICS) - Update click-outside handler to only handle showDepthSlider This simplifies the Document Graph UI as part of the mind map refactor. The ForceGraph component continues to use its internal default physics. --- .../DocumentGraph/DocumentGraphView.tsx | 167 +----------------- 1 file changed, 3 insertions(+), 164 deletions(-) diff --git a/src/renderer/components/DocumentGraph/DocumentGraphView.tsx b/src/renderer/components/DocumentGraph/DocumentGraphView.tsx index c92d6b75..dab40a6e 100644 --- a/src/renderer/components/DocumentGraph/DocumentGraphView.tsx +++ b/src/renderer/components/DocumentGraph/DocumentGraphView.tsx @@ -24,8 +24,6 @@ import { Sliders, Focus, AlertCircle, - Settings2, - RotateCcw, } from 'lucide-react'; import type { Theme } from '../../types'; import { useLayerStack } from '../../contexts/LayerStackContext'; @@ -33,7 +31,7 @@ import { MODAL_PRIORITIES } from '../../constants/modalPriorities'; import { Modal, ModalFooter } from '../ui/Modal'; import { useDebouncedCallback } from '../../hooks/utils'; import { buildGraphData, ProgressData, GraphNodeData } from './graphDataBuilder'; -import { ForceGraph, ForceGraphNode, ForceGraphLink, convertToForceGraphData, ForcePhysicsSettings, DEFAULT_PHYSICS } from './ForceGraph'; +import { ForceGraph, ForceGraphNode, ForceGraphLink, convertToForceGraphData } from './ForceGraph'; import { NodeContextMenu } from './NodeContextMenu'; import { GraphLegend } from './GraphLegend'; @@ -113,8 +111,6 @@ export function DocumentGraphView({ const [includeExternalLinks, setIncludeExternalLinks] = useState(defaultShowExternalLinks); const [neighborDepth, setNeighborDepth] = useState(defaultNeighborDepth); const [showDepthSlider, setShowDepthSlider] = useState(false); - const [showPhysicsPanel, setShowPhysicsPanel] = useState(false); - const [physics, setPhysics] = useState(DEFAULT_PHYSICS); // Selection state const [selectedNodeId, setSelectedNodeId] = useState(null); @@ -810,159 +806,6 @@ export function DocumentGraphView({ External - {/* Physics Settings */} -
- - - {showPhysicsPanel && ( -
-
- - Force Settings - - -
- - {/* Center Force */} -
-
- - Center Force - - - {physics.centerForce.toFixed(2)} - -
- setPhysics(prev => ({ ...prev, centerForce: parseFloat(e.target.value) }))} - className="w-full" - style={{ accentColor: theme.colors.accent }} - /> -

- Pulls nodes toward the center -

-
- - {/* Repel Force */} -
-
- - Repel Force - - - {physics.repelForce} - -
- setPhysics(prev => ({ ...prev, repelForce: parseInt(e.target.value, 10) }))} - className="w-full" - style={{ accentColor: theme.colors.accent }} - /> -

- Pushes nodes apart -

-
- - {/* Link Force */} -
-
- - Link Force - - - {physics.linkForce.toFixed(2)} - -
- setPhysics(prev => ({ ...prev, linkForce: parseFloat(e.target.value) }))} - className="w-full" - style={{ accentColor: theme.colors.accent }} - /> -

- Pulls connected nodes together -

-
- - {/* Link Distance */} -
-
- - Link Distance - - - {physics.linkDistance}px - -
- setPhysics(prev => ({ ...prev, linkDistance: parseInt(e.target.value, 10) }))} - className="w-full" - style={{ accentColor: theme.colors.accent }} - /> -

- Target distance between connected nodes -

-
-
- )} -
- {/* Refresh Button */}
- ) : ( - + ) : ( +
+ +

No focus document selected

+

Select a document to view its connections

+
)} {/* Graph Legend */} @@ -1034,7 +1037,7 @@ export function DocumentGraphView({ )}
- Click to select • Double-click to open • Drag to move • Scroll to zoom • Esc to close + Click to select • Double-click to recenter • O to open • Arrow keys to navigate • Esc to close From 99ee215672d246c6c06fbaae25c9c439d1ea766e Mon Sep 17 00:00:00 2001 From: Pedram Amini Date: Tue, 30 Dec 2025 13:29:05 -0600 Subject: [PATCH 06/10] MAESTRO: Remove standalone Document Graph from Command-K menu Remove the Document Graph entry from the Command-K quick actions menu. Document Graph can now only be opened when a specific file is selected, via right-click context menu or file preview panel. - Remove onOpenDocumentGraph prop from QuickActionsModalProps interface - Remove Document Graph action from mainActions array - Remove onOpenDocumentGraph from AppModals.tsx interfaces and usage - Remove onOpenDocumentGraph callback from App.tsx --- src/renderer/App.tsx | 1 - src/renderer/components/AppModals.tsx | 6 ------ src/renderer/components/QuickActionsModal.tsx | 7 +------ 3 files changed, 1 insertion(+), 13 deletions(-) diff --git a/src/renderer/App.tsx b/src/renderer/App.tsx index 0d4fa3e9..6489d07b 100644 --- a/src/renderer/App.tsx +++ b/src/renderer/App.tsx @@ -8618,7 +8618,6 @@ function MaestroConsoleInner() { getDocumentTaskCount={getDocumentTaskCount} onAutoRunRefresh={handleAutoRunRefresh} onOpenMarketplace={handleOpenMarketplace} - onOpenDocumentGraph={() => setIsGraphViewOpen(true)} tabSwitcherOpen={tabSwitcherOpen} onCloseTabSwitcher={handleCloseTabSwitcher} onTabSelect={handleUtilityTabSelect} diff --git a/src/renderer/components/AppModals.tsx b/src/renderer/components/AppModals.tsx index 8558330c..2aff131f 100644 --- a/src/renderer/components/AppModals.tsx +++ b/src/renderer/components/AppModals.tsx @@ -823,7 +823,6 @@ export interface AppUtilityModalsProps { getDocumentTaskCount: (filename: string) => Promise; onAutoRunRefresh: () => Promise; onOpenMarketplace?: () => void; - onOpenDocumentGraph?: () => void; // TabSwitcherModal tabSwitcherOpen: boolean; @@ -989,7 +988,6 @@ export function AppUtilityModals({ getDocumentTaskCount, onAutoRunRefresh, onOpenMarketplace, - onOpenDocumentGraph, // TabSwitcherModal tabSwitcherOpen, onCloseTabSwitcher, @@ -1106,7 +1104,6 @@ export function AppUtilityModals({ onPublishGist={onPublishGist} onInjectOpenSpecPrompt={onInjectOpenSpecPrompt} onOpenPlaybookExchange={onOpenMarketplace} - onOpenDocumentGraph={onOpenDocumentGraph} /> )} @@ -1835,7 +1832,6 @@ export interface AppModalsProps { getDocumentTaskCount: (filename: string) => Promise; onAutoRunRefresh: () => Promise; onOpenMarketplace?: () => void; - onOpenDocumentGraph?: () => void; tabSwitcherOpen: boolean; onCloseTabSwitcher: () => void; onTabSelect: (tabId: string) => void; @@ -2119,7 +2115,6 @@ export function AppModals(props: AppModalsProps) { getDocumentTaskCount, onAutoRunRefresh, onOpenMarketplace, - onOpenDocumentGraph, tabSwitcherOpen, onCloseTabSwitcher, onTabSelect, @@ -2413,7 +2408,6 @@ export function AppModals(props: AppModalsProps) { getDocumentTaskCount={getDocumentTaskCount} onAutoRunRefresh={onAutoRunRefresh} onOpenMarketplace={onOpenMarketplace} - onOpenDocumentGraph={onOpenDocumentGraph} tabSwitcherOpen={tabSwitcherOpen} onCloseTabSwitcher={onCloseTabSwitcher} onTabSelect={onTabSelect} diff --git a/src/renderer/components/QuickActionsModal.tsx b/src/renderer/components/QuickActionsModal.tsx index d00ed95a..9689f6f7 100644 --- a/src/renderer/components/QuickActionsModal.tsx +++ b/src/renderer/components/QuickActionsModal.tsx @@ -109,8 +109,6 @@ interface QuickActionsModalProps { onInjectOpenSpecPrompt?: (prompt: string) => void; // Playbook Exchange onOpenPlaybookExchange?: () => void; - // Document Graph - onOpenDocumentGraph?: () => void; } export function QuickActionsModal(props: QuickActionsModalProps) { @@ -133,8 +131,7 @@ export function QuickActionsModal(props: QuickActionsModalProps) { onCloseAllTabs, onCloseOtherTabs, onCloseTabsLeft, onCloseTabsRight, isFilePreviewOpen, ghCliAvailable, onPublishGist, onInjectOpenSpecPrompt, - onOpenPlaybookExchange, - onOpenDocumentGraph + onOpenPlaybookExchange } = props; const [search, setSearch] = useState(''); @@ -402,8 +399,6 @@ export function QuickActionsModal(props: QuickActionsModalProps) { { id: 'goToFiles', label: 'Go to Files Tab', shortcut: shortcuts.goToFiles, action: () => { setRightPanelOpen(true); setActiveRightTab('files'); setQuickActionOpen(false); } }, { id: 'goToHistory', label: 'Go to History Tab', shortcut: shortcuts.goToHistory, action: () => { setRightPanelOpen(true); setActiveRightTab('history'); setQuickActionOpen(false); } }, { id: 'goToAutoRun', label: 'Go to Auto Run Tab', shortcut: shortcuts.goToAutoRun, action: () => { setRightPanelOpen(true); setActiveRightTab('autorun'); setQuickActionOpen(false); } }, - // Document Graph - ...(onOpenDocumentGraph ? [{ id: 'documentGraph', label: 'Document Graph', shortcut: shortcuts.documentGraph, subtext: 'Visualize markdown file relationships', action: () => { onOpenDocumentGraph(); setQuickActionOpen(false); } }] : []), // Playbook Exchange - browse and import community playbooks ...(onOpenPlaybookExchange ? [{ id: 'openPlaybookExchange', From 920725a1db3bf1cbc02ec0e58f3378c84bbc4444 Mon Sep 17 00:00:00 2001 From: Pedram Amini Date: Tue, 30 Dec 2025 13:31:46 -0600 Subject: [PATCH 07/10] MAESTRO: Update GraphLegend for mind map layout - Replace circular force-graph node previews with card-style document nodes showing title + description representation - Replace external node circle with pill-shaped domain node - Add keyboard shortcuts section (arrows, Enter, O key) - Update edge previews to use bezier curves matching mind map style - Add KeyboardBadge component for displaying keyboard shortcuts - Update mouse interaction hints (click, double-click, right-click, scroll) - Update descriptions to match new mind map visual design --- .../components/DocumentGraph/GraphLegend.tsx | 243 ++++++++++++++---- 1 file changed, 186 insertions(+), 57 deletions(-) diff --git a/src/renderer/components/DocumentGraph/GraphLegend.tsx b/src/renderer/components/DocumentGraph/GraphLegend.tsx index 45dfd524..ea0702ba 100644 --- a/src/renderer/components/DocumentGraph/GraphLegend.tsx +++ b/src/renderer/components/DocumentGraph/GraphLegend.tsx @@ -1,18 +1,18 @@ /** - * GraphLegend - Component explaining node types, edge types, and colors in the Document Graph. + * GraphLegend - Component explaining node types, edge types, and keyboard shortcuts in the Mind Map. * * Displays a collapsible legend panel showing: - * - Document nodes: Markdown files with their distinctive styling - * - External link nodes: Aggregated external URLs by domain + * - Document nodes: Card-style nodes with title and description + * - External link nodes: Smaller pill-shaped nodes with domain * - Internal edges: Solid lines connecting markdown documents * - External edges: Dashed lines connecting to external domains - * - Selection state: Highlighted appearance when selected + * - Keyboard shortcuts: Arrow keys to navigate, Enter to recenter, O to open * - * The legend is theme-aware and uses the same colors as the actual graph elements. + * The legend is theme-aware and uses the same colors as the actual mind map elements. */ import React, { useState, memo, useCallback } from 'react'; -import { ChevronDown, ChevronUp, ArrowRight, AlertTriangle } from 'lucide-react'; +import { ChevronDown, ChevronUp, AlertTriangle, ExternalLink } from 'lucide-react'; import type { Theme } from '../../types'; /** @@ -45,16 +45,24 @@ interface EdgeLegendItem { description: string; } +/** + * Legend item for a keyboard shortcut + */ +interface KeyboardShortcutItem { + keys: string; + description: string; +} + const NODE_ITEMS: NodeLegendItem[] = [ { type: 'document', label: 'Document', - description: 'Markdown file (size = connections)', + description: 'Card with title and description', }, { type: 'external', label: 'External Link', - description: 'External domain (smaller, dimmer)', + description: 'Pill showing domain name', }, ]; @@ -62,7 +70,7 @@ const EDGE_ITEMS: EdgeLegendItem[] = [ { type: 'internal', label: 'Internal Link', - description: 'Connection between markdown documents', + description: 'Connection between markdown files', }, { type: 'external', @@ -71,8 +79,23 @@ const EDGE_ITEMS: EdgeLegendItem[] = [ }, ]; +const KEYBOARD_SHORTCUTS: KeyboardShortcutItem[] = [ + { + keys: '↑ ↓ ← →', + description: 'Navigate between nodes', + }, + { + keys: 'Enter', + description: 'Recenter on focused node', + }, + { + keys: 'O', + description: 'Open file in preview', + }, +]; + /** - * Mini preview of a document node for the legend (force graph style) + * Mini preview of a document node card for the legend (mind map style) */ const DocumentNodePreview = memo(function DocumentNodePreview({ theme, @@ -83,26 +106,62 @@ const DocumentNodePreview = memo(function DocumentNodePreview({ }) { return ( - + {/* Title line */} + + {/* Description line */} + + {/* Description line 2 */} + + {/* Open icon */} + + + ); }); /** - * Mini preview of an external link node for the legend (force graph style) + * Mini preview of an external link node pill for the legend (mind map style) */ const ExternalNodePreview = memo(function ExternalNodePreview({ theme, @@ -113,19 +172,32 @@ const ExternalNodePreview = memo(function ExternalNodePreview({ }) { return ( - + {/* Domain text representation */} + ); @@ -144,8 +216,9 @@ const EdgePreview = memo(function EdgePreview({ highlighted?: boolean; }) { const strokeColor = highlighted ? theme.colors.accent : theme.colors.textDim; - const strokeWidth = highlighted ? 2.5 : 1.5; + const strokeWidth = highlighted ? 2 : 1.5; const isDashed = type === 'external'; + const opacity = type === 'external' && !highlighted ? 0.5 : 0.8; return ( - - {/* Arrow head */} + {/* Curved bezier path to match mind map style */} ); }); /** - * GraphLegend component - Displays an explanation of graph elements + * Keyboard shortcut badge + */ +const KeyboardBadge = memo(function KeyboardBadge({ + keys, + theme, +}: { + keys: string; + theme: Theme; +}) { + return ( + + {keys} + + ); +}); + +/** + * GraphLegend component - Displays an explanation of mind map elements */ export const GraphLegend = memo(function GraphLegend({ theme, @@ -197,7 +287,7 @@ export const GraphLegend = memo(function GraphLegend({ style={{ backgroundColor: theme.colors.bgActivity, border: `1px solid ${theme.colors.border}`, - maxWidth: 280, + maxWidth: 300, zIndex: 10, // Position at bottom center bottom: 16, @@ -205,7 +295,7 @@ export const GraphLegend = memo(function GraphLegend({ transform: 'translateX(-50%)', }} role="region" - aria-label="Graph legend" + aria-label="Mind map legend" > {/* Header - Always visible */}