Skip to content

feat(library): add waypoint editing to straight edges - #834

Merged
FelixTJDietrich merged 9 commits into
mainfrom
feat/straight-edge-customization
Jul 28, 2026
Merged

feat(library): add waypoint editing to straight edges#834
FelixTJDietrich merged 9 commits into
mainfrom
feat/straight-edge-customization

Conversation

@FelixTJDietrich

@FelixTJDietrich FelixTJDietrich commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Summary

Straight connections in use-case, syntax-tree, and Petri-net diagrams currently offer no way to correct a route without moving its nodes. This PR gives those edges a direct, discoverable waypoint-editing workflow:

  • Select or hover a straight edge to reveal filled circular bend handles.
  • Drag a segment handle to create a waypoint, then drag that waypoint freely in two dimensions.
  • Hold Shift while dragging to snap to familiar 15-degree angles.
  • Remove a waypoint by double-clicking it, focusing it and pressing Delete, or dragging it back onto the straight route.
  • Reconnect an endpoint without losing the route, or reset the edge once to clear every custom waypoint.

The handles intentionally share the opaque blue visual state of step-edge bend handles. They remain circular because a straight-edge waypoint moves in two dimensions, while a step-edge capsule represents a segment constrained to one axis.

This PR is deliberately limited to manual editing. Automatic routing and syntax-tree layout are separated into the follow-up PR #835 so each change can be reviewed and released independently.

Release note

Shape diagonal connections by hand just like orthogonal ones. Use-case, syntax-tree,
and petri-net connections now have filled circular waypoints: drag the handle on a
segment to add one, drag an existing point to reshape the route, and double-click,
press Delete, or drag it magnetically back onto the line to remove it. Shift-drag locks
to familiar 15-degree angles, endpoint reconnection preserves the custom route, and a
single reset clears all hand-authored routing.

Implementation notes

  • Stores only user-authored interior waypoints. Existing diagrams without waypoints keep their current route.
  • Advances the additive wire format to 4.2.0. Imports from 4.0/4.1 discard only inert straight-edge route caches so they cannot appear as new bends; orthogonal waypoints and all other model data remain intact, while future 4.x waypoint data is left untouched.
  • Feeds the resulting polyline through the existing label and line-jump geometry instead of treating each segment as an unrelated edge.
  • Keeps endpoint reconnection, undo/redo, serialization, and diagram-version conversion aware of custom routes.
  • Keeps the published TypeScript surface source-compatible. A declaration-level comparison against main contains only the new optional moveEdgeWaypoint label; complete translation dictionaries written for earlier releases still compile and receive the English fallback internally.
  • Uses an invisible 24 px hit target for comfortable pointer and keyboard interaction while rendering a compact circular handle.
  • Gives a visible waypoint ownership of its exact grab centre even when a nearby endpoint's larger reconnect target overlaps it; the endpoint grip remains independently reachable beside the node.
  • Scales midpoint spacing with zoom so fixed-screen hit targets do not merge into an ambiguous interaction area when zoomed out.
  • Keeps pointer-only midpoint handles out of the keyboard tab order; authored waypoints remain named and focusable for Delete/Backspace removal.
  • Replaces the browser's square SVG focus outline with a visible darkened-circle focus state. This preserves keyboard feedback without introducing a focus treatment that step-edge handles do not have.
  • Offsets only straight-edge reconnect targets from node handles. Existing orthogonal/step-edge reconnect geometry remains unchanged; the full E2E suite caught and now guards that boundary.
  • Keeps automatic route selection out of this PR. The editor does not add or move waypoints unless the user directly manipulates the edge.
  • Accounts explicitly for the feature's eager bundle cost: the Node 22 CI measurement is 119.56 kB brotli, so the main-entry budget moves from 118 kB to 121 kB. This adds 1.44 kB of headroom without adding a runtime dependency.

Steps for testing

  1. Open a use-case, syntax-tree, or Petri-net diagram and create or select a straight connection.
  2. Confirm that its circular handles are fully opaque blue on hover/selection and that no square focus ring appears when a handle receives keyboard focus.
  3. Drag a segment handle away from the line; confirm that it becomes a persistent waypoint and that labels and line jumps follow the reshaped path.
  4. Drag a waypoint with and without Shift; confirm free movement and 15-degree snapping.
  5. Remove a waypoint by each supported path: Delete, double-click, and dragging it back onto the line.
  6. Reconnect either endpoint and confirm the interior route is retained.
  7. Use the edge's reset action and confirm all custom waypoints are cleared in one undoable change.
  8. Import a 4.0/4.1 straight-edge model with legacy data.points; confirm it remains visually straight, while an orthogonal edge retains its existing manual bends.
  9. Run pnpm lint && pnpm format:check && pnpm build && pnpm test.
  10. Run pnpm exec playwright test tests/e2e/straight-edge-waypoint-ux.spec.ts --project chromium --project firefox from standalone/webapp.
  11. Run pnpm --filter @tumaet/apollon run size; the main entry should remain below 121 kB brotli.

Local verification on this branch after rebasing onto current main: 88 unit-test files passed (1,781 tests; 1 skipped), and the main published entry is 119.71 kB brotli against its 121 kB budget. The focused production interaction and legacy-import suite passed all 7 tests in both Chromium and Firefox (14 browser runs total), including real pointer drags where waypoint and endpoint targets are close together and a one-move quick-drag regression.

Screenshots / screencasts

A selected syntax-tree connection with an added circular waypoint and opaque segment handles

Captured from this branch's production build after adding a waypoint. The focused Playwright suite covers what the still cannot show: drag, magnetic collapse, overlapping-target ownership, hover, keyboard removal, and a computed-style comparison against step-edge handles.

Checklist

  • Linked to a related issue (not applicable; no issue captures the manual-editing scope)
  • Added a changeset whose summary is written in the user's voice (pnpm changeset, how)
  • PR title's Conventional Commit type (feat) matches the user-visible feature and release-note group
  • Tests added or updated
  • Ran pnpm lint && pnpm format:check && pnpm build && pnpm test locally — green
  • Documentation updated (the model contract now documents 4.2 migration and compatibility behavior)
  • Screenshots or screencasts attached

@Claudia-Anthropica Claudia-Anthropica left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@FelixTJDietrich The waypoint workflow and migration coverage look solid overall. One pointer-event edge case can still make a valid new-waypoint drag disappear on release; see the inline comment.

Comment thread library/lib/hooks/useStraightPathEdge.ts Outdated
@github-project-automation github-project-automation Bot moved this from Backlog to In progress in Apollon Development Jul 28, 2026

@Claudia-Anthropica Claudia-Anthropica left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@FelixTJDietrich The quick-drag handoff now preserves the threshold-crossing move, and the focused regression covers the original failure mode. Looks good.

@FelixTJDietrich
FelixTJDietrich merged commit dc7f071 into main Jul 28, 2026
26 checks passed
@github-project-automation github-project-automation Bot moved this from In progress to Done in Apollon Development Jul 28, 2026
@FelixTJDietrich
FelixTJDietrich deleted the feat/straight-edge-customization branch July 28, 2026 12:33
@github-actions github-actions Bot mentioned this pull request Jul 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants