Skip to content

Comments

graph visuals update#127

Merged
pedramamini merged 10 commits intomainfrom
graph-visuals
Dec 30, 2025
Merged

graph visuals update#127
pedramamini merged 10 commits intomainfrom
graph-visuals

Conversation

@pedramamini
Copy link
Collaborator

No description provided.

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
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
- 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.
Create new deterministic canvas-based mind map visualization for the
Document Graph feature, replacing the physics-based force-directed graph:

- MindMapNode/MindMapLink interfaces for typed graph data
- MindMapProps requiring centerFilePath (no standalone mode)
- calculateMindMapLayout() - BFS layout algorithm that:
  - Centers focus document in middle
  - Splits depth-1 docs into alphabetized left/right columns
  - Clusters external URLs at bottom (sorted by domain)
  - Supports depth 2+ nodes fanning out from parents
- Canvas rendering with themed document/external nodes
- Document nodes show title + description with truncation
- External nodes render as smaller pills with domain only
- Open file icon in document node corners
- Keyboard nav: arrows to move, Enter to recenter, O to open
- Mouse: click to select, double-click to recenter, drag/scroll
- Search highlighting with dimmed non-matching nodes
- convertToMindMapData() utility for graphDataBuilder integration
- Update DocumentGraphView.tsx to use MindMap component:
  - Replace ForceGraph import with MindMap import
  - Change focusFilePath from optional to required
  - Update state types to MindMapNode/MindMapLink
  - Add handleOpenFile callback for mind map navigation
  - Update footer with mind map keyboard shortcuts

- Update App.tsx for required focusFilePath:
  - Conditionally render DocumentGraphView only when graphFocusFilePath is set
  - Clear graphFocusFilePath on close
  - Remove onFocusFileConsumed prop
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
- 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
The force-directed graph visualization has been replaced by a deterministic
canvas-based mind map layout. ForceGraph.tsx is no longer used - all imports
now reference MindMap.tsx instead.
- Removed react-force-graph-2d from package.json dependencies
- Updated DocumentGraphView.tsx header comment to reflect canvas-based MindMap
- Ran npm install to clean up package-lock.json (16 packages removed)
- Updated graphDataBuilder.test.ts comment to reference MindMap.tsx instead of ForceGraph.tsx
- Rewrote GraphLegend.test.tsx (557 lines) to match new MindMap-style legend:
  - Updated aria-label expectations from "graph legend" to "Mind map legend"
  - Node preview tests now expect card-style SVG rects instead of circles
  - Edge preview tests now expect bezier paths instead of lines with arrow heads
  - Updated text descriptions for NODE_ITEMS and EDGE_ITEMS
  - Added tests for Keyboard Shortcuts, Status Indicators, interaction hints
  - Updated max-width from 280px to 300px
  - Updated stroke-dasharray from "4 4" to "4 3" for bezier styling
@pedramamini pedramamini merged commit 6e56a5e into main Dec 30, 2025
2 checks passed
@pedramamini pedramamini deleted the graph-visuals branch December 30, 2025 20:14
@claude
Copy link

claude bot commented Dec 30, 2025

Code Review - PR #127: Graph Visuals Update

This is an impressive refactor that replaces the physics-based force-directed graph with a deterministic canvas-based mind map. The implementation is well-structured and follows the codebase conventions. Here's my detailed review:

✅ Strengths

1. Architecture & Design

  • Clean separation of concerns: The new MindMap.tsx (1,141 lines) is well-organized with clear sections: types, constants, utilities, layout algorithm, and rendering
  • Deterministic layout: The BFS-based layout algorithm provides predictable, reproducible positioning - a major UX improvement over physics simulations
  • Performance: Canvas-based rendering is the right choice for graph visualization, avoiding DOM overhead
  • Type safety: Comprehensive TypeScript interfaces (MindMapNode, MindMapLink, MindMapProps)

2. Code Quality

  • Excellent documentation: Every function has clear JSDoc comments explaining purpose and behavior
  • Consistent naming: Uses standard graph terminology (nodes, edges/links, depth, BFS)
  • Constants organization: Well-defined layout constants (spacing, sizes, offsets) at the top make tuning easy
  • Test updates: GraphLegend.test.tsx properly updated (89 additions, 70 deletions) to match new mind map styling

3. Accessibility & UX

  • Keyboard navigation: Comprehensive arrow key navigation with spatial awareness (lines 922-1034)
  • Visual feedback: Hover states, selection highlighting, and search dimming
  • Accessibility: Proper tabIndex, ARIA labels updated in tests
  • Progressive disclosure: Depth slider for focused ego-network views

4. Integration

  • Clean removal: Properly removed react-force-graph-2d dependency (16 packages removed from lock file)
  • Backwards compatibility: No breaking changes to external APIs
  • Settings cleanup: Removed obsolete documentGraphLayoutMode setting throughout the stack

⚠️ Issues & Concerns

1. Security: Potential XSS in External Link Handling ⚠️
In MindMap.tsx:991:

window.open(focusedNode.urls?.[0], '_blank');

Issue: No validation of URL scheme before opening. Malicious markdown could use javascript: URLs.
Fix: Add URL validation:

const url = focusedNode.urls?.[0];
if (url && (url.startsWith('http://') || url.startsWith('https://'))) {
  window.open(url, '_blank');
}

2. Performance: Inefficient Node Searching 🐌
Multiple places use find() in event handlers (lines 827, 866, 891):

const node = findNodeAtPoint(x, y);
// findNodeAtPoint does: nodesWithState.find(n => ...)

Issue: O(n) search on every mouse move event
Suggestion: Consider spatial indexing (quadtree) if node count grows beyond ~100 nodes, or at minimum cache the result when mouse position hasn't changed

3. Code Duplication: Left/Right Column Logic
Lines 360-394 have nearly identical logic for left and right columns:

// Calculate positions for left column
const leftX = centerX - (HORIZONTAL_SPACING * depth);
const leftTotalHeight = leftNodes.length * VERTICAL_SPACING;
// ... repeat for right

Suggestion: Extract to a positionColumn() helper function to reduce duplication

4. Magic Numbers
Line 909: const delta = -e.deltaY * 0.001;
Line 225: const controlOffset = Math.min(dx * 0.5, 100);
Line 942: const leftColumn = nodesWithState.filter(n => n.x < focusedNode.x - 50);

Suggestion: Define as named constants (e.g., ZOOM_SENSITIVITY, BEZIER_CONTROL_FACTOR, COLUMN_DETECTION_THRESHOLD)

5. Missing Error Boundary
MindMap.tsx is a complex component with canvas operations but lacks error handling for:

  • Canvas context failures (getContext('2d') can return null)
  • Layout calculation errors (empty nodes array, missing center node)

Suggestion: Add error boundaries or null checks, especially around canvas operations

6. Test Coverage Gaps
While GraphLegend.test.tsx was updated, I don't see tests for:

  • MindMap.tsx core functionality (layout algorithm, keyboard navigation, mouse interactions)
  • calculateMindMapLayout() function
  • convertToMindMapData() utility

Recommendation: Add unit tests for the layout algorithm and integration tests for user interactions

7. Accessibility: Keyboard Focus Indication
The keyboard navigation is well-implemented, but there's no visual focus ring for keyboard users when navigating with arrow keys. The focused node is only marked internally (focusedNodeId state).

Suggestion: Add a distinct visual indicator (e.g., dotted outline) for keyboard-focused nodes, separate from mouse-selected nodes

📝 Minor Issues

1. Type Strictness
Line 294: const { id, depth } = queue.shift()!;
The non-null assertion (!) is safe here due to the while (queue.length > 0) check, but consider:

const item = queue.shift();
if (!item) continue;
const { id, depth } = item;

2. Inconsistent Naming

  • NODE_HEIGHT_BASE vs NODE_HEIGHT_WITH_DESC (abbreviated)
  • EXTERNAL_CLUSTER_OFFSET vs full names elsewhere

3. Comment Typo
Line 2: "A complete rewrite from force-directed graph to a clean, centered mind map layout."
Consider adding "Replaces ForceGraph.tsx" for clarity in git history.

4. Unused Import
Check if all imports in DocumentGraphView.tsx are used after the refactor (saw RotateCcw, Settings2 removed).

🎯 Performance Considerations

1. Canvas Rendering

  • Good: Single canvas element, no DOM thrashing
  • Good: useMemo for layout calculations (line 468)
  • Good: useCallback for event handlers

2. Potential Optimization
Consider adding a shouldComponentUpdate equivalent if re-renders become expensive with large graphs:

const prevNodesRef = useRef(nodes);
if (prevNodesRef.current === nodes) return; // Skip render if data unchanged

🔒 Security Assessment

No SQL injection risks (no database queries)
No command injection (no shell commands)
File path handling: Appears safe, uses relative paths
⚠️ XSS risk: External URL handling (see issue #1 above)
Input sanitization: Search query appears safe (no innerHTML usage)

📊 Code Metrics

Metric Value Assessment
Files changed 16 Reasonable for refactor
Additions 1,517 Large but expected
Deletions 1,355 Good cleanup
Net change +162 Minimal bloat
New component size 1,141 lines Consider splitting if grows
Test coverage Partial Needs improvement

🚀 Recommendations

High Priority:

  1. ✅ Fix XSS vulnerability in URL handling
  2. ✅ Add unit tests for MindMap component
  3. ✅ Add error boundaries for canvas operations

Medium Priority:
4. Extract duplicate column layout logic
5. Add keyboard focus visual indicator
6. Convert magic numbers to named constants

Low Priority:
7. Consider spatial indexing for large graphs
8. Add performance monitoring for render time
9. Document the layout algorithm with diagrams

✨ Conclusion

This is a well-executed refactor that significantly improves the Document Graph feature. The code is clean, well-documented, and follows the project's conventions (as outlined in CLAUDE.md). The main concerns are:

  1. Security: XSS vulnerability in external URL handling (must fix)
  2. Testing: Missing test coverage for core new component (should add)
  3. Performance: Minor optimization opportunities for large graphs

After addressing the XSS issue and adding basic tests, this PR is ready to merge. The deterministic layout is a major UX improvement over the previous physics-based approach.

Approval Status: ⚠️ Approve with changes - Fix XSS issue before merging

Great work on this refactor! The mind map approach is much more intuitive than force-directed graphs for document relationships.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant