Skip to content

feat(graph): compact nodes, so more of a large graph fits in view (v0.21.0) - #328

Merged
MerciHanrim merged 1 commit into
mainfrom
feat/compact-nodes
Oct 7, 2026
Merged

MerciHanrim merged 1 commit into
mainfrom
feat/compact-nodes

Conversation

@MerciHanrim

@MerciHanrim MerciHanrim commented Oct 7, 2026 •

Copy link
Copy Markdown
Owner

Part of #325, PR 3 of 3. Version 0.21.0 (the release date is set to the actual merge day before merging). The contract is docs/flow-colour-and-compact-nodes.md, FC-7.

What changes

  • Shorter, a little narrower: a one-line node is 56 px tall instead of 64 (BASE_NODE_H in src/components/nodes/silhouette.ts, the .nodef floor in src/index.css), with 12 px of inline padding instead of 16. Source and Drain keep 22 px instead of 26 at their pointed end, Gate 26 instead of 30.
  • Content still decides: 56 is a floor, not a forced height. A one-line Pool is 58, which its title and value need; a two-line title, a capacity row, every Parameter and every Register keep the height their content needs. The title's maximum width and the End's 24 px right padding are unchanged, so long titles wrap where they did.
  • Ports and hit areas: the visible ports and their 18 px hit area keep their size; the click and drag areas do not shrink.
  • Silhouettes: silhouettePath is fully parametric from 56; at 64 every kind still returns its historic path byte for byte. Below 64 the End and Register caps meet at mid-height, so no outline has a negative or reversed curve at any height.
  • Display priority: selection, focus, invalid, run and Focus-mode marks keep their order over flow colours.
  • LOD: LOD thresholds were not tuned; the existing LOD views are regression-checked on the compact geometry.

Measured

Kind Before After
Source, Drain, Converter, Gate, End (one line) 64 56
Pool (one line) 64 58
Parameter, Register by content by content, unchanged
Content-driven width — 8 px narrower
  • Measured on the 386 nodes of the bundled templates plus a sample of every kind, by the same script on the branch point and on this tree: every node is at its predicted height, and 235 got shorter.

What does not change

  • Node positions, saved diagrams, share links, the file format, the engine digests and simulation results. Connections attach 3 to 4 px higher and orthogonal routes are recomputed.
  • Routing: src/store/routeMap.ts falls back to BASE_NODE_H for an unmeasured node and test/routeCases.ts to 56; the auto-frame fallback (150 × 40) is unchanged. ROUTER_VERSION is unchanged and test/fixtures/routes/golden-routes.json stays byte-identical to e763eeb.

Gacha template: one waypoint

  • With compact nodes the two Premium Pickup +1 labels of e_pickup_34 and e_pickup_36 overlapped in Korean, because the band between the first and second rows got narrower.
  • Layout round 7 in scripts/gen-gacha-banner-zones-example.ts gives e_pickup_36 one waypoint, {x: 3200, y: 650}, which routes it into the band under the second row. No node moves and the shared label logic is untouched. The regenerated examples/gacha-banner-zones.json differs only by that waypoint.
  • Digests: the engine digest is unchanged; the content and full digests are pinned at their new value in src/engine/templateFlowColours.test.ts. sha256Baseline.test.ts keeps the recorded feat(about): show open-source licences and check them at build time #301 values: its legacy projection removes accent and exactly this one waypoint, and fails if the waypoint is anything else.
  • Router golden: the golden test projects out exactly this waypoint (WAYPOINTS_ADDED_SINCE_GOLDEN in test/routeCases.ts), and the route with it is pinned in its own case.
  • e2e/gacha-banner-zones.spec.ts checks that the two labels keep clear of each other in English, Korean and Japanese.

Visual baselines

  • 41 existing baselines change with the compact geometry, each reviewed against its before image and its diff and approved before it was updated: canvas-refresh-visual 12, flow-colour-views-visual 9 (the three templates among them), playback-visual 7, flow-colour-visual 5, large-graph-readability 4, forced-colors-edge-tell 2, i18n-visual 1, model-nodes-visual 1. No baseline was added.
  • 14 baselines that were expected to move are left as they are, because they pass within their policy tolerance (full-page shots, L0 and minimap views).
  • Updated on a freshly started dev server checked to serve this branch's version; two runs in a row without an update then passed.

Tests

  • Unit: src/components/nodes/silhouette.test.ts rewritten (54: the historic paths at 64, the floor, every integer height in bounds and without a reversed curve, the exact End and Register paths at 56); the split digest tests above; the router golden and its new case.
  • End to end: e2e/node-long-label.spec.ts pins the one-line Pool at 58 and a Source at 56; e2e/edge-routing.spec.ts compares the label position with the route's unrounded midpoint; e2e/gacha-banner-zones.spec.ts adds the label check; e2e/whats-new.spec.ts pins 0.21.0.
  • Copy guards move only their exact pins: catalog 1027 to 1030, runtime 1249 to 1252, pt-PT's difference from pt-BR 274 to 275, a new ё word for ru. No bound is widened.

Verification (local, at the head commit)

  • npx tsc -b, oxlint (39 warnings, the existing baseline, 0 errors), 3,207 unit tests, all 21 source checks of the CI checks job, and the list of 1,993 tests in exactly one of the 5 shards.
  • End to end in Chrome on a freshly started dev server, without retries: every screenshot spec on chromium and mobile twice in a row, 321 passed and 5 skipped by design each time; the whole mobile project 109 passed, 4 skipped by design; the related specs (long labels, edge routing, the gacha template, What's new, LOD, i18n-vi, large-graph readability, template viewport and labels, flow colour and its views, canvas lock, dense-graph pan) 378 passed; the portable file 16 of 16, the production bundle 16 of 16, the PWA 19 of 19.

CI

  • Run 37574794813 at d36946c, the head: every job passed and the union is exact (1,993: 1,983 passed, 7 skipped by design, 0 failed), with three retries, all in shard 2, kept as a record and not re-run.
  • toolbar-locale-width.spec.ts:72 zh-Hans and zh-Hant: each first attempt timed out after 8 s waiting for the locale to switch from en and passed on the retry; the slowdown tracked in test(e2e): the zh-Hant descriptive-copy wrapping test slows down on CI and ended a browser session #305.
  • playback-a11y-background.spec.ts:127 on mobile: the first attempt's console held one dev-server message, the Vite reload socket to localhost:5173 refused, which the shared no-console-errors check counts; the playback assertions passed, and the retry passed. This pull request changes neither playback nor the dev server.
  • The Cloudflare preview of the head serves v0.21.0 · build d36946c, and its automated check against production passed 21 of 21 with no page error: one-line Source, Drain, Gate, Converter and End 56 and a one-line Pool 58 on desktop and phone (64 on production), each silhouette's viewBox following its height; Parameter, Register and a Pool with a capacity row at their production height; every port's drawn size and hit area as on production; every node of the three templates at its production position, none taller (Coffee 9 of 23 shorter, gacha 44 of 63, MMO 66 of 97); and the two gacha +1 labels clear of each other in English, Korean and Japanese.

Not claimed

  • No manual check of this pull request's preview; its Cloudflare preview is checked by automation.
  • No manual screen-reader check.
  • 16 of the 18 languages have not been reviewed by a native speaker.

….21.0)

Part of #325, PR 3 of 3. Version 0.21.0. Contract: docs/flow-colour-and-compact-nodes.md FC-7.

Geometry: a one-line node is 56 px tall instead of 64 (BASE_NODE_H in src/components/nodes/silhouette.ts, the .nodef floor in src/index.css), with 12 px of inline padding instead of 16; Source and Drain keep 22 px instead of 26 at their pointed end and Gate 26 instead of 30. 56 is a floor, not a forced height: a one-line Pool is 58, which its title and value need, and a two-line title, a capacity row, every Parameter and every Register keep the height their content needs. The title's maximum width, the End's 24 px right padding, the visible ports and their 18 px hit area are unchanged. Measured on the 386 nodes of the bundled templates plus a sample of every kind: every node is at its predicted height, 235 got shorter.

Silhouettes: silhouettePath is now fully parametric from 56; at 64 every kind still returns its historic path byte for byte. Below 64 the End and Register caps meet at mid-height, so no outline has a negative or reversed curve at any height from 56 to the kind's maximum (silhouette.test.ts walks every integer height).

Routing: src/store/routeMap.ts falls back to BASE_NODE_H for an unmeasured node, and test/routeCases.ts to 56; the auto-frame fallback is unchanged. ROUTER_VERSION is unchanged and test/fixtures/routes/golden-routes.json stays byte-identical to e763eeb.

Gacha template: with compact nodes the two Premium Pickup `+1` labels of e_pickup_34 and e_pickup_36 overlapped in Korean. Layout round 7 in scripts/gen-gacha-banner-zones-example.ts gives e_pickup_36 one waypoint, {x: 3200, y: 650}, which routes it into the band under the second row; no node moves and the shared label logic is untouched. The regenerated examples/gacha-banner-zones.json differs only by that waypoint. Its engine digest is unchanged; its content and full digests are pinned at their new value in src/engine/templateFlowColours.test.ts. sha256Baseline.test.ts keeps the recorded #301 values: its legacy projection removes accent and exactly this one waypoint. The golden router test projects out exactly this waypoint (WAYPOINTS_ADDED_SINCE_GOLDEN in test/routeCases.ts) and the new route is pinned in its own case. e2e/gacha-banner-zones.spec.ts checks that the two labels keep clear of each other in English, Korean and Japanese.

Unchanged: node positions, saved diagrams, share links, the file format, the engine digests and simulation results; connections attach 3 to 4 px higher and orthogonal routes are recomputed. Selection, focus, invalid, run and Focus-mode marks keep their order over flow colours. LOD thresholds were not tuned; the existing LOD views are regression-checked on the compact geometry.

Tests: silhouette.test.ts rewritten (54 tests); node-long-label.spec.ts pins the one-line Pool at 58 and a Source at 56; edge-routing.spec.ts compares the label position with the route's unrounded midpoint; whats-new.spec.ts pins 0.21.0. Three release-note lines in 18 languages, 16 without native review; the copy guards move only their exact pins (catalog 1027 to 1030, runtime 1249 to 1252, pt-PT's difference from pt-BR 274 to 275, a new ё word for ru), no bound widened. Docs: the contract's FC-7, CHANGELOG.md and README.md.

Pixel baselines: 41 existing baselines change with the compact geometry, each reviewed against its before image and diff and approved before it was updated: canvas-refresh-visual 12, flow-colour-views-visual 9 (the three templates among them), playback-visual 7, flow-colour-visual 5, large-graph-readability 4, forced-colors-edge-tell 2, i18n-visual 1 and model-nodes-visual 1. 14 baselines that were expected to move stay as they are, because they pass within their policy tolerance (full-page shots, L0 and minimap views). No baseline was added.
@MerciHanrim
MerciHanrim merged commit 6de1852 into main Oct 7, 2026
10 checks passed
@MerciHanrim
MerciHanrim deleted the feat/compact-nodes branch October 7, 2026 05:49
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.

1 participant