diff --git a/packages/memory-graph/CHANGELOG.md b/packages/memory-graph/CHANGELOG.md index f2902a01..7e52aef0 100644 --- a/packages/memory-graph/CHANGELOG.md +++ b/packages/memory-graph/CHANGELOG.md @@ -20,7 +20,7 @@ **Feature:** When a popover is opened for a doc/memory node, the background dims while the selected node and popover remain in full focus. **Implementation:** -- Smooth animated dimming: 200ms ease-out cubic transition +- Smooth animated dimming: 1500ms ease-out cubic transition - Canvas-based dimming: non-selected nodes reduced to 20% opacity - Edges not connected to selected node reduced to 10% opacity - Selected node remains at full opacity (1.0) for clear focus @@ -37,28 +37,28 @@ - Multiple ways to close: click backdrop, click X button, or press Escape key **Files Changed:** +- `src/constants.ts:108-114` - Added ANIMATION config with dimDuration - `src/components/node-popover.tsx:3,20-29` - Escape key handler and transparent backdrop -- `src/components/graph-canvas.tsx:53-54,62-91,289,294,301,306,317,435,454,577` - Smooth animation and dimming logic +- `src/components/graph-canvas.tsx:12,53-54,62-91,289,294,301,306,317,435,454,577` - Smooth animation and dimming logic - `src/components/memory-graph.tsx:620` - Pass selectedNodeId to canvas - `src/types.ts:86` - Added selectedNodeId prop to GraphCanvasProps ---- - -## Visual & Layout Improvements (2025-12-21) - ### Smart Positioning Node Popover **Feature:** Clicking nodes now shows a floating popover with detailed information, positioned near the node with smart viewport edge detection. **Implementation:** - DOM-based popover -- Auto-positions to avoid viewport edges +- Auto-positions to avoid viewport edges with proper gap from node +- Popover positioned next to node (not on top) with 20px gap +- Calculates node dimensions dynamically based on type (document vs memory) +- Flips to opposite side when approaching viewport edges - Click-outside to close - Shows all node metadata: title, summary (2-line truncation), type, memory count, URL, creation date, and ID - For memories: includes space, expiration date (if applicable), and forgotten status **Files Changed:** - `src/components/node-popover.tsx` - New popover component -- `src/components/memory-graph.tsx` - Smart positioning logic +- `src/components/memory-graph.tsx:421-429,434` - Smart positioning logic with gap calculation ### Document Type Icons on Cards **Feature:** Document cards now display type-specific icons centered on the card for better visual identification. diff --git a/packages/memory-graph/src/components/graph-canvas.tsx b/packages/memory-graph/src/components/graph-canvas.tsx index 066c0d0b..76acd89c 100644 --- a/packages/memory-graph/src/components/graph-canvas.tsx +++ b/packages/memory-graph/src/components/graph-canvas.tsx @@ -9,7 +9,7 @@ import { useRef, useState, } from "react" -import { colors } from "@/constants" +import { colors, ANIMATION } from "@/constants" import type { DocumentWithMemories, GraphCanvasProps, @@ -63,7 +63,7 @@ export const GraphCanvas = memo( // Smooth dimming animation useEffect(() => { const targetDim = selectedNodeId ? 1 : 0 - const duration = 200 // milliseconds + const duration = ANIMATION.dimDuration // Match physics settling time const startDim = dimProgress.current const startTime = Date.now() diff --git a/packages/memory-graph/src/components/memory-graph.tsx b/packages/memory-graph/src/components/memory-graph.tsx index 70ee5470..d98fb42b 100644 --- a/packages/memory-graph/src/components/memory-graph.tsx +++ b/packages/memory-graph/src/components/memory-graph.tsx @@ -416,17 +416,22 @@ export const MemoryGraph = ({ // Popover dimensions (estimated) const popoverWidth = 320 const popoverHeight = 400 - const offset = 40 const padding = 16 + // Calculate node dimensions to position popover with proper gap + const nodeSize = selectedNodeData.size * zoom + const nodeWidth = selectedNodeData.type === "document" ? nodeSize * 1.4 : nodeSize + const nodeHeight = selectedNodeData.type === "document" ? nodeSize * 0.9 : nodeSize + const gap = 20 // Gap between node and popover + // Smart positioning: flip to other side if would go off-screen - let popoverX = screenX + offset - let popoverY = screenY - 20 + let popoverX = screenX + nodeWidth / 2 + gap + let popoverY = screenY - popoverHeight / 2 // Check right edge if (popoverX + popoverWidth > containerSize.width - padding) { // Flip to left side of node - popoverX = screenX - popoverWidth - offset + popoverX = screenX - nodeWidth / 2 - gap - popoverWidth } // Check left edge @@ -446,7 +451,7 @@ export const MemoryGraph = ({ } return { x: popoverX, y: popoverY } - }, [selectedNodeData, zoom, panX, containerSize.width, containerSize.height]) + }, [selectedNodeData, zoom, panX, panY, containerSize.width, containerSize.height]) // Viewport-based loading: load more when most documents are visible (optional) const checkAndLoadMore = useCallback(() => { diff --git a/packages/memory-graph/src/constants.ts b/packages/memory-graph/src/constants.ts index 5ee74e9e..8badd89f 100644 --- a/packages/memory-graph/src/constants.ts +++ b/packages/memory-graph/src/constants.ts @@ -7,15 +7,15 @@ export const colors = { }, document: { primary: "rgba(255, 255, 255, 0.21)", // Subtle glass white - secondary: "rgba(255, 255, 255, 0.12)", // More visible - accent: "rgba(255, 255, 255, 0.18)", // Hover state + secondary: "rgba(255, 255, 255, 0.31)", // More visible + accent: "rgba(255, 255, 255, 0.31)", // Hover state border: "rgba(255, 255, 255, 0.6)", // Sharp borders glow: "rgba(147, 197, 253, 0.4)", // Blue glow for interaction }, memory: { primary: "rgba(147, 196, 253, 0.21)", // Subtle glass blue - secondary: "rgba(147, 197, 253, 0.16)", // More visible - accent: "rgba(147, 197, 253, 0.24)", // Hover state + secondary: "rgba(147, 196, 253, 0.31)", // More visible + accent: "rgba(147, 197, 253, 0.31)", // Hover state border: "rgba(147, 196, 253, 0.6)", // Sharp borders glow: "rgba(147, 197, 253, 0.5)", // Blue glow for interaction }, @@ -105,6 +105,12 @@ export const GRAPH_SETTINGS = { }, } +// Animation settings +export const ANIMATION = { + // Dim effect duration - shortened for better UX + dimDuration: 1500, // milliseconds +} + // Responsive positioning for different app variants export const POSITIONING = { console: {