Skip to content

Rover.fly_to/4 and Rover.fit_to/4 — a view that is a gesture, not state - #4

Merged
nseaSeb merged 1 commit into
mainfrom
feat/fly-to
Aug 6, 2026
Merged

Rover.fly_to/4 and Rover.fit_to/4 — a view that is a gesture, not state#4
nseaSeb merged 1 commit into
mainfrom
feat/fly-to

Conversation

@nseaSeb

@nseaSeb nseaSeb commented Aug 6, 2026

Copy link
Copy Markdown
Owner

center and zoom are attributes, which is right when the view is a property of what you are rendering. It is the wrong tool for "the user clicked a row, take me there": passing center costs you the automatic framing (fit falls back to false, the centre stops being derived), so you trade the default behaviour for one gesture and hold the view in assigns from then on.

{:noreply, Rover.fly_to(socket, "clients", {client.lat, client.lon}, zoom: 15)}
{:noreply, Rover.fit_to(socket, "fleet", vehicles_on_shift, max_zoom: 15)}

Commands, not state. Nothing assigned, no attribute changed — and because the config never moves, the next unrelated re-render cannot pull the view back. The suite asserts exactly that: fly to Paris, recolour a parcel, check the centre held.

Rover.bbox/1 is public alongside them: markers, shapes, plain coordinates, a mixed list, or a box passed through. It drops unusable coordinates rather than raising, matching <.map>.

Two of the three new guards were worthless until sabotaged

This is the part worth reading.

  • The fit assertion compared the new zoom >= the old one — satisfied by doing nothing at all. Stubbing fitTo to return immediately still passed. The playground now fits a single marker with max_zoom: 17, so the assertion is an exact zoom that inaction cannot reach, and it covers the max_zoom plumbing as a side effect.
  • The id filter had nothing to be wrong about with one map on the page. Removing it passed. Hence a second map in the playground — which also demonstrates two maps in one LiveView, a capability nobody had verified.

All three now fail when broken:

Sabotage Result
id filter removed 1 failed
fitTo does nothing 1 failed
max_zoom ignored 1 failed

148 Elixir tests, 48 Node tests, 7 browser scenarios.

🤖 Generated with Claude Code

…ot state

`center` and `zoom` are attributes, which is right when the view is a property of
what you are rendering. It is the wrong tool for "the user clicked a row, take me
there": passing `center` costs you the automatic framing — `fit` falls back to
false and the centre stops being derived — so you trade the default behaviour for
one gesture and hold the view in assigns from then on.

These are commands instead. push_event carries the destination, nothing is
assigned, no attribute changes, and because the config never moves the next
unrelated re-render cannot pull the view back — which the browser suite asserts
by recolouring a parcel after flying and checking the centre held.

Both name the map's DOM id, because push_event reaches every hook on the page.
Without that filter two maps in one LiveView both fly, so the playground now
carries a second map and the suite checks it stayed put.

Rover.bbox/1 is public alongside them: markers, shapes, plain coordinates, a mixed
list, or a box passed through. It drops coordinates it cannot use rather than
raising, for the same reason <.map> does — framing is a convenience and
third-party geometry arrives in whatever projection it arrives in.

Two of the three new guards were worthless until the sabotage pass caught them:

- The fit assertion compared the new zoom `>=` the old one, which is satisfied by
  doing nothing at all. The playground now fits a single marker with max_zoom: 17,
  so the assertion is an exact zoom that cannot be reached by inaction — and it
  covers the max_zoom plumbing as a side effect.
- The id filter had nothing to be wrong about with one map on the page. Hence the
  second map, which also demonstrates a capability nobody had verified.

148 Elixir tests, 48 Node tests, 7 browser scenarios.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@nseaSeb
nseaSeb merged commit 02fa109 into main Aug 6, 2026
7 checks passed
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