Skip to content

Improve canvas connection feel: snapping, magnetic handles, duplicate guards, calmer preview - #4

Merged
clioo merged 1 commit into
clioo:mainfrom
rashidazarang:canvas-feel
Aug 6, 2026
Merged

clioo merged 1 commit into
clioo:mainfrom
rashidazarang:canvas-feel

Conversation

@rashidazarang

Copy link
Copy Markdown
Contributor

What

Four small quality-of-life changes to how connecting and arranging feels on the canvas, adapted from studying how n8n and React Flow's own examples tune theirs:

  1. Grid snapping — snapToGrid with a 12px grid (half the 24px background dot gap), so dragged nodes line up without needing an organize pass.

  2. Magnetic handles — connectionRadius={60}: dropping a connection near a handle attaches it instead of silently cancelling. This is the single biggest "why didn't my connection take?" fix.

  3. Duplicate-connection guard — hasEquivalentEdge (in graphUtils) compares connections after createEdge's handle normalization. It's enforced in both paths:

    • the store's addEdgeFromConnection now returns whether it added, and the connect tool toasts "These nodes are already connected" instead of stacking an invisible second edge;
    • isValidConnection gives the same feedback live during a drag.

    Reverse edges (b → a) and first loops are still allowed; a second identical edge/loop is not.

  4. Calmer connection preview — the drag-out line waits 300ms before appearing, so an accidental press on a handle no longer flashes a stray line. When it appears it uses the same smooth-step styling as committed edges (var(--accent), dashed).

Tests

  • graphUtils.test.ts: equivalence across default handles, reversed direction, distinct handle pairs, loops.
  • store.test.ts: duplicate connect is a no-op (edge count and revision unchanged, so undo history stays clean), reverse edge and first loop still allowed.
npm test          # 31 passed + 7 companion (no new failures)
npm run build     # clean

Note: the two storage-failure tests in store.test.ts fail on main before this branch — that's #3, independent of this change.

…uplicate guards

Four small quality-of-life changes to how connecting and arranging feels,
adapted from studying how n8n and React Flow's own examples tune their
canvases:

- Snap dragging to a 12px grid (half the 24px background dot gap), so
  nodes line up without an organize pass.
- connectionRadius=60 makes handles magnetic: dropping a connection near
  a handle attaches it instead of silently cancelling.
- Duplicate connections are refused everywhere: hasEquivalentEdge compares
  connections after createEdge's handle normalization, the store's
  addEdgeFromConnection now returns whether it added (the connect tool
  toasts "These nodes are already connected"), and isValidConnection gives
  the same feedback live during a drag. Reverse edges and first loops are
  still allowed; a second identical loop is not.
- The drag-out connection preview waits 300ms before appearing, so an
  accidental press on a handle no longer flashes a stray line. The preview
  uses the same smooth-step styling as committed edges.

Note: the two storage failure tests in store.test.ts fail on main before
this change (see the separate fix PR); no new failures are introduced.
@clioo
clioo merged commit e112f5e into clioo:main Aug 6, 2026
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.

2 participants