KeelrLeek 52b1b8e622 artist page: keep the album reveal's target reachable
Opening an album juddered: the page ran at the clicked row, then stopped
dead just short of it.

revealIntoView lifts the row to the banner line, which needs a pane-height of
content beneath that row. Until the previous commit the pane's ~2000px of dead
scroll always supplied it. With the range ending at the content, a row in the
last screenful no longer has it, so the reveal eased toward a scrollTop the
range could not hold and slammed into the clamp — measured on a 29-album artist:
target 1846 against a max of 1594, 272px in a single frame, then 39 frames
pinned, and the row parked 598px below the line instead of on it. Not a race
with the expander either; it finishes growing at ~500ms and the target is still
252px out of reach.

Reserve the row's own pane-height, the same way the grid already reserves one
for the tab bar so a tab switch cannot clamp the scroll — extended to the open
expander's row and released when it closes.

- On the grid's min-height, because that is what moves this page: .scrollbody's
  height does not answer to padding at all (border-box against a fixed height —
  0px, 200px and 600px of padding-bottom all measured the same 1787px box).
- Reserved, not predicted. The expander's height is not the page's growth: the
  slack in this very reserve swallowed 435 of a 486px panel, so a 486px expander
  grew the page by 66.
- Stood up synchronously by the reveal as well as by measureCols, which only
  recomputes off a ResizeObserver — that fires after the 420ms animation has
  already parked against the old clamp.
- Released on the expander's destroy. measureCols cannot notice the panel
  leaving: the raised min-height is exactly what stops the grid's box from
  changing, so the observer sees nothing and the reserve would stick for the
  rest of the visit, leaving a screenful of empty page under the grid.
- Re-measured across the settle after an open. What moves the target row is the
  card art this very click asked for; those images land over the following few
  hundred ms and rows above the row grow as they do (measured: the row sat 488px
  into the grid when the reveal read it, 555px once settled). Only the first
  open of a page pays this.
- The reveal clamps its target regardless and idles on it for up to a second, so
  a corrected reserve still completes the travel instead of ending short.

Verified on a 29-album artist and an 11-album one: every open lands the row at
exactly the 280px line, first open of a fresh page included, with no direction
reversals and no frames against the clamp. Frame timing improves on both —
cold 13 frames over 16ms (worst 79.6) to 2 (worst 60.6, the album fetch and
decode, which predates this), warm 2 (worst 18.4) to 0 (worst 9). The pane's
scroll range still ends exactly at the content with no expander open, and
returns to it on close.
2026-07-24 18:25:58 -05:00
S
Description
SoulSeek Streaming app.
9.5 MiB
1 Stars 2 Watchers 1 Forks
Languages
Rust 48.3%
Svelte 38.1%
JavaScript 13.4%
CSS 0.2%