v0.16.0 — magnetic docking - #21
Merged
Merged
Conversation
Connect by touching instead of by drawing. Drag a symbol — in from the palette, or one already on the sheet — so one of its connection points comes within about 18 screen px of another symbol's, and a ring marks the point it has caught while every connection point on the sheet lights up. Let go and the symbol clicks into place, the two points landing on exactly the same spot, with the line already drawn between them. Because a line stores PORTS and not coordinates, pulling the pair apart afterwards stretches the pipe instead of breaking it. Details that make it behave - The line class comes from the two port kinds, not the toolbar: a controller docking onto a valve's signal boss gets signal.electric even with a process class selected. Incompatible pairings never dock at all. - The reach is judged in SCREEN px so it feels the same at any zoom, clamped in sheet space so an extreme zoom can neither make it unhittable nor grabby enough to swallow neighbouring symbols. - A pair that is already joined will not dock again, so nudging a docked symbol cannot stack a second identical line on the first. - The symbol and the line it docked onto are ONE undo step, whether they came from the palette (addBatch) or from a drag across the sheet (dockNode). - The hint ring lives inside .joint-layers, the group carrying the pan/zoom transform, so it sits on the sheet rather than floating over the viewport. - The palette exports the drag in flight, because dragover is not allowed to read dataTransfer — browsers only hand the payload over on drop — and the canvas needs to know WHAT is being dragged to preview where it would dock. Also honours prefers-reduced-motion: the ring still marks the spot, it just stops pulsing. Tests: 10 unit cases over findDock/dockEdge/dockRadius covering rotation, zoom clamping, closest-candidate selection, incompatible ports and the already-joined guard; 3 e2e covering a palette drop that docks, a drop clear of everything that simply lands, and a drag that docks then stretches when pulled away. Co-Authored-By: Claude Opus 5 (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.
Connect by touching instead of by drawing.
Drag a symbol — in from the palette, or one already on the sheet — so one of its
connection points comes within ~18 screen px of another symbol's, and a ring
marks the point it has caught while every connection point lights up. Let go and
the symbol clicks into place, the two points landing on exactly the same spot,
with the line already drawn.
Because a line stores ports and not coordinates, pulling the pair apart
afterwards stretches the pipe instead of breaking it.
Details that make it behave
onto a valve's signal boss gets
signal.electriceven with a process classselected. Incompatible pairings never dock.
in sheet space so an extreme zoom can neither make it unhittable nor grabby
enough to swallow neighbouring symbols.
stack a second identical line on the first.
from the palette (
addBatch) or a drag across the sheet (dockNode)..joint-layers, the group carrying the pan/zoomtransform, so it sits on the sheet rather than floating over the viewport.
One change on top of the original work
Added a
prefers-reduced-motionguard so the ring stops pulsing for users whoask for less motion — it still marks the spot. The rest of this stylesheet
already honours that, so the new animation was the odd one out.
Verification
npm run build— cleannpm test— 724 passing (10 new:findDock/dockEdge/dockRadius,covering rotation, zoom clamping, closest-candidate selection, incompatible
ports, and the already-joined guard)
npx playwright test— 62 passing, 1 skipped (3 new: a palette drop thatdocks, a drop clear of everything that simply lands, and a drag that docks
then stretches when pulled away)
🤖 Generated with Claude Code