Repository navigation
v0.27.0 — move a connection's end without drawing it again - #352
Merged
Merged
Conversation
…e or another node, the connection kept docs/edge-routing.md §ER18, the first line-editing unit. One check and one change for every surface (src/model/endMove.ts `endMoveVerdict`, the store's `moveEdgeEnds`); the Inspector's Ends group is the first surface, the canvas end grips come next. - A move keeps the connection: id, kind, direction, handles and every data field (amount or condition, resource type, colour, line shape, the user's bends). Only the end node and its side (`data.ports`, canonical) change. - Refused, with the reason shown: an end on a node without the port this kind needs there (a Source has no input, a Drain or End no output, a Parameter or Register no ports); and, only when a node changes, a result that repeats another connection by the drawing rule (same ends and stored handles, as xyflow's addEdge refuses), the moved connection excluded. A side change alone is never a duplicate: the examples hold parallel connections. Drawing runs the same duplicate check before it records, so a refused drawing no longer adds an undo entry or resets the run. - One undo step per applied move; a cancel, a refusal or the same ends record nothing. A side-only move keeps the run (`ports` is decoration on undo and redo too); a node change resets it. - The user's bends are never removed; one the bend rule would refuse at the new ends is said before applying. - The Ends group: per end a node list and a four-side choice, then Apply (one change) or Revert. A node that cannot take the end is disabled with its reason in the option's own text; the reason, the bend warning and the result are in a status line the controls are described by. Node names are bidi-isolated. Not on the phone (read-only); disabled under the edit lock. - 21 strings in 18 languages; pt-BR writes three neutral lines as pt-PT does, so pt-PT's region delta stays 280. The locale tests' counts and the Russian ё list follow. Contract tests only; no native-speaker review. Tests: src/store/graphStore.endMove.test.ts (17, including the parallel connections of state-verification and the Early MMO); e2e connection-ends.spec.ts (6). Related e2e (974): 965 passed; of the four failures, two are fixed here (an Inspector input selector met the new radios first: the group now sits below Route; the phone showed radios: the group is not offered there) and two are the Inspector snapshots in state-ui.spec.ts (light, dark), which change by this group and are NOT updated: their before / after awaits review.
…ace, or pick a side; the Ends group folds docs/edge-routing.md §ER18. The canvas surface for moving a connection's end, through the same check and change as the Inspector's Ends group. - Grips on the ONE selected connection only (nothing else selected): never on hover, not on the phone, not under the edit lock. Each grip is a named button. - Drag a grip onto a node's face: the end moves (one undo step). A drop on a face the check refuses changes nothing and says why (live region and the Ends status line); elsewhere, or after Esc, nothing changes and nothing is recorded. The drag is React Flow's connection engine (XYHandle), started from a mouse press or a touch start: React Flow's own reconnect anchors listen to the mouse only (spike, share note 43), so they are not used, and drawing a new connection is untouched. - A drag in progress is cancelled, applying nothing, if the grips go away under it (deselected, deleted, the lock turned on); after Esc, moving on or releasing does nothing. - Click, tap, Enter or Space on a grip: the four sides of that end's node as buttons around it (past its outside name where the name is on that side), the current one marked; a choice moves the end and closes them, Esc or a press elsewhere closes them unchanged; focus returns to the grip. - The Ends group is folded by default to its name and a From → To summary (the design review: always open, it pushed Colour out of view). Opened, the pick and Apply as before; folding drops a pick not applied; the status line stays visible while folded. - @xyflow/system 0.0.81 (the version @xyflow/react 12.11.5 pins) is now a direct dependency, since the grips import XYHandle from it; it already shipped and is in the third-party manifest. - 3 strings in 18 languages (the summary, the two grip names); the summary's arrow is a `graph-relation` arrow, kept unmirrored in Arabic as the canvas it describes is (scripts/arrow-units.json); the node names entering ICU arguments are declared in scripts/isolate-obligations.json (13 rows) and counted in scripts/icu-argument-disposition.json. Locale tests' counts and identical-to-English lists follow. Contract tests only; no native review. Tests: e2e connection-ends.spec.ts 25 (the Ends group, the fold, the grips by mouse, touch and keyboard, the side choice, every cancellation, the phone and the lock). Related e2e (984 tests): 985 passed, 5 skipped, 2 failed — the two state-ui Inspector snapshots, which change by this group and are NOT updated: before / after (opened and folded) await the design review (share notes 42, 45). Unit 3 555. Build and third-party notices ok.
…4 px for touch, clear of every port docs/edge-routing.md §ER18 (share note 46). The grips and the side buttons live in the zoomed flow layer, so at zoom 0.5 a 24 px grip was a 12 px target. Each is now scaled back by the zoom: a grip is a 24 x 24 screen px target with a 10 px dot at every zoom, 44 x 44 while any pointer of the device is coarse (`data-coarse`, from `(any-pointer: coarse)`; no second media breakpoint, as scripts/check-mobile-query.mjs requires); the side buttons are at least as large and placed by their own size. Centred on its port, a grip covered that port (so a new connection could not be drawn from it while the connection was selected, e.g. the Coffee roastery's fan) and, at zoom 0.5 or with a touch target, the node's other ports. A grip now sits half its target plus 2 px out along its end's stub, as React Flow's own reconnect anchors are offset: no port meets a grip's target on the small fixture or the Coffee fan at zoom 0.5, 1 and 2, mouse and touch (before: one to three ports per grip). Ctrl+click adds a second connection to the selection on this branch and on main e7efd77 alike (Meta and Shift replace it on both); the multi-select e2e now holds Control on the keyboard (Playwright's mouse.click has no modifier option) instead of setting the second selection in the store. e2e connection-ends.spec.ts: 26 (+ the 24 px / 10 px dot / no-port check at three zooms and the 44 px / no-port check with touch).
state-ui.spec.ts Inspector snapshots, light and dark, regenerated from the final code: the Ends group folded to one line (Ends · Feeder → Tank) above the drawing note, Colour in view again. Reviewed and approved (share notes 42, 45); only these two baselines change. Re-run after writing: 2 passed.
…gain - package.json / package-lock.json 0.27.0; `.changes/move-connection-end.json` (user-facing, `release:0.27.0`). - What's new 0.27.0, three lines in 18 languages: move an end by dragging a grip onto a side of another node, or with Ends in the Inspector, the amount, condition, colour, line shape and bends kept; click or tap a grip to pick a side of the same node, the phone read-only as before; a move that cannot be made is not applied and says why. None claims more than that: turning a connection around, user curves and label moving are not in it. - es-ES says `móvil` where es-419 says `teléfono` (one audited key more); pt-BR and pt-PT write all three lines identically and regionally neutral (`em uma`, `em volta`, `telefone`), so pt-PT's region delta stays 280. The locale tests' counts and the Russian ё list (`щёлкните`) follow. The e2e release list pins 0.27.0. Contract tests only; no native review. - CHANGELOG v0.27.0; README Latest — v0.27.0 (v0.26.2 kept as a section, v0.24.0 moved into the CHANGELOG list).
…ses checked, not a guarantee
docs/edge-routing.md §ER18, CHANGELOG v0.27.0 and two e2e test titles said
a grip's target is clear of every port. That holds for the cases measured
(the small fixture and the Coffee fan, zoom 0.5 to 2, mouse and touch: no
port met a grip's target), not for every layout: a port of another node
close to a stub, or a very short stub, can still meet it. The wording now
says so; the `8ee7aec` subject ("clear of every port") is not rewritten.
Text only: no product code, no test logic (the two titles say "on this
fixture"); connection-ends.spec.ts 26 passed after the change.
Deploying cozy-loop-studio with
|
| Latest commit: |
e0aaeaf
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://5b81af37.cozy-loop-studio.pages.dev |
| Branch Preview URL: | https://feat-move-connection-end.cozy-loop-studio.pages.dev |
…e side choice is a popover naming its node docs/edge-routing.md §ER18 (share notes 46, 47). The review of the grips moved out along the stub found two handling problems on the Coffee fan (touch, zoom 0.5): the source grip sat on the fan's shared trunk and took presses meant for the two sibling connections, and the side buttons spread around the node covered the neighbouring nodes' names and ports. - A grip sits on its connection's own line at the nearest FREE spot near its end: from half its target plus 2 px past the port, then 8, 16 and 24 screen px further in (24 px, one mouse target: beyond it the dot no longer reads as this end's), never past the middle of the line. Free = nothing else a press could reach under the whole target (another connection's line, a port, a node, the other grip; the browser's elementsFromPoint on a 5 x 5 grid) and no text covered (any connection label, its own too, or an outside name). - No free spot: no grip. A small hollow mark (not focusable, not a pointer target, not announced) shows the end, and the Ends group says, folded or open, that the canvas has no free spot for that end's grip and that the end moves from there (2 strings x 18). No large transparent target takes presses from the lines around it. - The side choice is a small popover instead of buttons around the node: its title names the end and the node, the four sides in a cross, the current one marked; it opens beside the grip on the side away from the node it edits, stays inside the canvas, is never taller or wider than the canvas allows (it scrolls rather than cut a side off); Esc or a press elsewhere closes it, a choice moves the end; focus returns to the grip. No zoom is forced for touch. On the two scenes reviewed: the small fixture (mouse, zoom 1) keeps both grips, free; on the Coffee fan with touch at zoom 0.5 neither end has a free spot (marks and the Ends hint), at zoom 1 the target end has one. Tests: connection-ends.spec.ts 27 (the popover's name, place in the canvas and off its node, no side cut off; a grip's target with no port, label or name under it at zoom 0.5 / 1 / 2; an end with no spot: the mark is not focusable and the hint shows while folded; the 44 px touch tests at zoom 1.5). Locale tests' counts +2. Unit 3 555. Static checks pass.
… and where there is no grip The What's new line for the side choice (18 languages), the README Latest section and the CHANGELOG v0.27.0 entry said a side is chosen "around that node" and that every end has a grip. Since `1f7efd4` the sides are chosen in a small popover naming the node, and an end with no free spot near it has no grip: the Ends group in the Inspector moves it. The line now says both. Neutral wording kept identical in pt-BR and pt-PT; es-ES keeps `móvil`; Arabic names the popover a small window, the canvas being its `اللوحة`. Text only. Locale and release-note tests 713, whats-new.spec.ts and descriptive-copy-wrapping.spec.ts 121 passed; check:i18n, arrow, ICU, control-byte, glyph and change-declaration checks pass.
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.
v0.27.0 — move a connection's end without drawing it again
The first line-editing unit (
docs/edge-routing.md§ER18): an existing connection's source or target end moves to another side of its node or to another node, from the canvas or from the Inspector, through one shared check and one shared change. Eight commits, each verified and pushed as it was done.1. One check, one change (
822eb18)src/model/endMove.ts(endMoveVerdict,movedEdge) and the store'smoveEdgeEnds, used by every surface.data.ports, canonical) change.a_z2_*_lo/_hi, the choreography'sl_add/l_sub), and resource + state pairs. Policy closed by Lumi.portscounts as decoration on undo and redo too); a move to another node resets it.2. The Inspector's Ends group (
822eb18, folded in55ba9c6)Folded by default to its name and a From → To summary (the design review: always open, it pushed Colour out of view). Opened: a node list and a four-side choice per end, then Apply (one change) or Revert. A node that cannot take the end is listed disabled with its reason in its own text, so a keyboard or screen-reader user reads it; the status line (reason, bend warning, result, and an end with no grip on the canvas) stays visible while folded. Not on the phone; disabled under the edit lock.
3. The canvas end grips (
55ba9c6,8ee7aec,1f7efd4)XYHandle), started from a mouse press or a touch start. React Flow's own reconnect anchors listen to the mouse only (spike, share note 43), so they are not used, and drawing a new connection is untouched. A refused face changes nothing and says why (live region and Ends status line); a drop elsewhere, Esc, a deselection, a deletion or the lock during the drag change nothing and record nothing.8ee7aec): 24 × 24 screen px at every zoom with a 10 px dot, 44 × 44 while any pointer is coarse; the side buttons at least as large.@xyflow/system0.0.81 (the version@xyflow/react12.11.5 pins) is now a direct dependency, since the grips importXYHandle.1f7efd4, after the design review of note 46): a grip sits on its connection's own line at the nearest FREE spot near its end — the first spot past the port, then 8, 16 and 24 screen px further in (the dot's centre at most 38 px from the port with a mouse, 48 px with touch), never past the middle of the line. Free: nothing else a press could reach under the whole target (another connection's line, a port, a node, the other grip;elementsFromPointon a 5 × 5 grid) and no label or outside name covered. No free spot: no grip — a small mark, not focusable and not a target — and the Ends group says, folded or open, to move that end from there. Measured on the cases checked, not a guarantee for every layout.1f7efd4): click, tap, Enter or Space on a grip opens a small popover naming the end and its node, the four sides in a cross, the current one marked; it opens away from the node it edits, inside the canvas, never taller or wider than the canvas allows (it scrolls rather than cut a side off); a choice moves the end, Esc or a press elsewhere closes it unchanged; focus returns to the grip. No zoom is forced for touch.4. Release (
cea6ca5,8c639b7,e0aaeaf)cea6ca5regenerates the twostate-uiInspector snapshots (light, dark) with the folded group — the only baselines changed, approved after review (share notes 42, 45).8c639b7: 0.27.0,.changes/move-connection-end.json(user-facing), three What's new lines in 18 languages, CHANGELOG v0.27.0, README Latest.e0aaeaf(text only) brings the side-choice line, README and CHANGELOG in line with1f7efd4: a small panel naming the node, and Ends in the Inspector where the canvas has no room for a grip.móvilwhere es-419 saysteléfono; pt-BR and pt-PT write the release lines identically and neutrally, so pt-PT's region delta stays 280. The summary's arrow is agraph-relationarrow, kept unmirrored in Arabic (scripts/arrow-units.json); the node names entering ICU arguments are declared (scripts/isolate-obligations.json, 13 rows). The translation contract tests passing is evidence of the catalogs' structure, not of how natural the lines read; no native-speaker review was done.Verification (final head
e0aaeaf)--workers=1 --retries=0: 2 183 passed, 0 failed, 10 skipped (53.2 min).distandpwaconfigs, run separately after the full run:dist16 passed,pwa19 passed.graphStore.endMove.test.ts(17). tsc, lint (0 errors),check:change-declaration,check:i18n,check:i18n-surface,check:arrow-direction,check:isolate-arguments,check:icu-arguments,check:mobile-query, the direction and glyph checks,check:e2e-shards; build andcheck:third-party-noticeson the dependency change.connection-ends.spec.ts: 27 (the Ends group, the fold, the grips by mouse, touch and keyboard, the free-spot placement and the no-grip end, the popover, every cancellation, the target sizes, multi-selection, the phone and the lock).Earlier runs, kept as they were: the full local e2e on
8c639b7(2 182 passed, 0 failed, 10 skipped) withdist16 andpwa19 there, and CI 10 / 10 on6463fde; neither covers1f7efd4ore0aaeaf. Related e2e per step: 974 → 965 passed (two fixed, two pending baselines); 992 → 985 passed, 5 skipped, the two pending baselines (the55ba9c6message says "984 tests" for that run; it was 992).Notes
6463fdechanges TEXT only (CHANGELOG.md,docs/edge-routing.md§ER18, two e2e test TITLES): the grips' clearance of ports is stated as a measurement, not a guarantee. The8ee7aecsubject ("clear of every port") overstates it and is not rewritten.cea6ca5commit message file was written withprintf, not the editor tool; its text is intact and the history is not rewritten.Records and open items
Share notes 40–47 (the proposal and decisions, two defects, the Inspector baselines, the reconnect spike, the grips, the fold, the target sizes, the free-spot placement and the popover). Recorded, not fixed here (note 41): the Inspector's Type switch drops the colour and the sides and leaves
out/inon a new state connection; a Parameter or Register offers state handles a connection can be drawn from. Separate later units: turning a connection around, user curves, moving a connection's label.