feat(canvas): Phase 1 — Canvas core with home view and UX flow#10
Merged
feat(canvas): Phase 1 — Canvas core with home view and UX flow#10
Conversation
- Overview: user stories, UI flow diagrams, component tree, Context vs Zustand split, layer boundaries, file layout, engineering decisions - Phase 1.1: Vitest + testing-library, lucide-react, 9 shadcn UI components (Button, Input, Select, Textarea, Dialog, Sheet, Sidebar, Tooltip, Card) - Phase 1.2: BaseNodeShell + Start/LLM/End node presenters with Lucide icons - Phase 1.3: GraphCanvas container, Sidebar-based Toolbar, connection validation, canvas hint, starter template (Start+End pre-placed), graphSlice extensions - Phase 1.4: NodeConfigPanel using Sheet component, config forms, slide transition - Phase 1.5: HomeView with GraphCard grid, NewGraphDialog, editable graph name, save/load flow, view routing (home/canvas) - Updated plan READMEs to reflect Phase 5 merged, Phase 1 in progress Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add Vitest + @testing-library/react + jsdom test infrastructure - Add lucide-react for consistent iconography - Create 9 shadcn-style UI components: Button, Input, Select, Textarea, Dialog (native <dialog>), Sheet (slide-over panel), Sidebar (collapsible), Tooltip (CSS-only), Card (with interactive variant) - Create CanvasContext (selectedNodeId + ReactFlow instance) - Add @contexts path alias to tsconfig, vite, and vitest configs - Add canvas types (CanvasNode, CanvasEdge, C1NodeType) - 33 tests passing across 7 test files Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- BaseNodeShell: shared chrome with Lucide icon, label, type badge, configurable handles, selected state highlight - StartNode: Play icon, green accent, source handle only - LLMNode: Brain icon, blue accent, both handles, provider/model badge - EndNode: Square icon, red accent, target handle only - nodeTypes registry for React Flow - Node CSS styles: accent borders, selected ring, handle styles, pulse animation (for C2 run highlighting) - 16 tests for node components Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- GraphCanvas: container bridging React Flow <-> Zustand with connection validation (no self-connect, no Start as target, no End as source, no duplicate edges), drag-end position sync, edge deletion - Toolbar: Sidebar-based with Lucide icons, tooltips, collapse to icons - CanvasHint: contextual hint when canvas has <= 2 nodes - useNodeDrop: handles drag-to-add with node type defaults - graphSlice: updateNodePosition, addEdge, removeEdge, removeNodes, newGraph (starter template with Start+End connected), renameGraph - Mapping utilities: toRFNode, toNodeSchema, toRFEdge, toEdgeSchema - 37 new tests (70 total) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- NodeConfigPanel: container using Sheet component, dispatches to config forms based on node type with slide transition - StartNodeConfig: label-only form (dumb presenter) - LLMNodeConfig: provider, model, system prompt, temperature, max tokens - EndNodeConfig: label-only form (dumb presenter) - graphSlice.updateNodeConfig: partial merge for label and config - Delete node button with Trash2 icon - 19 new tests (89 total) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- HomeView: graph card grid with empty state illustration and CTA - GraphCard: dumb presenter with mini-preview dots, relative time - NewGraphDialog: modal for naming graphs before creation - CanvasHeader: back button, inline-editable graph name, save button - uiSlice: view routing (home/canvas), newGraphDialogOpen state - graphSlice: saveGraph, loadGraph, loadGraphList, deleteGraphById, persisted flag for create vs update distinction - useBeforeUnload: warns on tab close with unsaved changes - API layer: updateGraph, deleteGraph, listGraphs pagination unwrap - App.tsx: conditional rendering of HomeView or CanvasView - 30 new tests (119 total across 23 test files) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- API layer: match backend's {name, schema_json} request shape and
GraphResponse format. Add toGraphSchema converter for responses.
- GraphCanvas: replace direct Zustand-driven RF state with useReducer.
RF owns visual state (drag positions, selection, dimensions) locally
via applyNodeChanges/applyEdgeChanges. Meaningful events (drag end,
connect, delete) sync back to Zustand as source of truth. This
prevents stale-closure bugs during rapid RF interactions.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Indigo theme: replace blue with indigo across all components, nodes, handles, focus rings, pulse animation, and button primary variant - Design tokens: add @styles/tokens.ts as single source of truth for brand, node accent, surface, and feedback colors - IconButton: new rounded icon button component used in Dialog and Sheet close buttons with cursor-pointer - Toolbar: restructure as Card-based layout with icon, label, description, accent border, "Nodes" section header. Collapsed mode shows icon cards. - Dialog: center on page, remove border, use IconButton for close - NewGraphDialog: update title to "Create a new graph" - Button: add cursor-pointer to all variants - Add @Styles path alias to tsconfig, vite, and vitest configs Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove redundant type badges (START/LLM/END) — icon + accent is enough - Add tinted icons matching node accent colors - Compact nodes: reduce min-width to 120px, add depth shadow - Bezier edges with arrowhead markers showing flow direction - Edge reconnection: drag existing edge handle to rewire connections - Handle hover: scale up and accent-color on hover for discoverability - Prevent duplicate Start/End nodes in useNodeDrop - Edge hover: highlight in indigo on hover/select Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- api client: send X-API-Key from VITE_API_KEY env var, parse error detail from response body - Toast component: slide-in notification with auto-dismiss, replaces inline error text next to Save button - Drop-on-edge: dropping a node near an existing edge splits it, inserting the new node between source and target - Handle hover: subtle brightness change instead of jarring purple Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Switch from ConnectionMode.Loose to Strict so only source→target connections are allowed and valid handles highlight during drag. Add custom SnapConnectionLine component to match edge stroke styling. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add dropdown menu on GraphCard with Delete and Rename options. Delete opens a confirmation dialog; Rename opens a modal with pre-filled input. Refactor Card to use CardHeader/CardMedia/CardContent/CardFooter structure. Menu appears on card hover only. Add danger Button variant and DropdownMenu component. Add renameGraphById to store. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove isPanningRef pan-vs-click disambiguation that blocked all stamp placements (onPaneClick already only fires for clicks, not pans). Center floating toolbar vertically on left edge instead of bottom. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Disable singleton node buttons in the toolbar when they already exist on the canvas, and show an info toast when placement is blocked via drag-drop or stamp mode. Toast auto-dismisses after 3 seconds. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add floating toolbar with stamp-to-place and drag-to-drop node creation, stamp ghost preview, canvas routing, API key auth client, and remove obsolete Sidebar/Toolbar components replaced by the new FloatingToolbar. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move API key injection to Vite proxy (server-side only) so secrets never reach the browser bundle. Fix header spread order so caller options can override defaults. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add spliceEdge action to graphSlice that removes old edge and adds node + two new edges in a single set() call. Read nodes/edges via getState() inside placeNode to avoid stale closure captures. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace the inner try/catch that silently retried createGraph on 404 with a simple persisted ternary. Add ApiError with status property for structured error handling. Show toast on save failure for immediate user feedback. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
FloatingToolbar already handles Escape for both stamp clearing and toolbar collapse. The GraphCanvas handler was redundant and could fire out of order. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Wrap id with encodeURIComponent in getGraph, updateGraph, and deleteGraph to prevent path traversal if IDs contain special chars. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- CanvasHeader: replace local toast state with useUIStore.showToast so all error toasts go through the global toast system - NodeConfigPanel: replace unsafe `as unknown as` cast with isLLMNode type guard for proper type narrowing - FloatingToolbar: remove memo wrapper — it reads two stores on every render so memo provides no benefit Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Test plan
pnpm --filter @graphweave/canvas typecheckpassespnpm --filter @graphweave/canvas test— 156 tests pass (27 test files)🤖 Generated with Claude Code