mirror of
https://github.com/block/buzz.git
synced 2026-08-18 06:50:31 +02:00
Tyler's report: scrolling UP a fully-loaded channel is subtly jumpy;
DOWN is smooth. Root cause (Eva H1 + L-C): rows above the opening
viewport have never painted, so under content-visibility:auto they sit
at estimateRowHeight()'s contain-intrinsic-size reserve (60px,
utilities.css:17). Scrolling up, each realizes at its true height; the
reserve-vs-true delta shifts the reading position. Shipped WKWebView has
no overflow-anchor, so it corrects nothing — every delta lands raw.
This adds a deterministic gate that is RED at tip 77bd0e70 and that the
converged owned-compensation fix (overflow-anchor:none + same-frame
scrollBy(realized-reserved)) turns green:
- e2eBridge: a dedicated `jitter-corpus` mock channel (400 structurally
heterogeneous rows — headings/lists/blockquotes/code fences/long prose
whose true height estimateRowHeight is known to miss), its own channel
so the uniform deep-history seed the load-older specs use is untouched.
- upscroll-jitter.perf.ts: forces overflow-anchor:none on the scroller
(mirrors shipped WKWebView; logs CSS.supports per engine), then wheels
up in notches tracking a row held INSIDE the viewport (SAFE_MARGIN band
from both edges, re-picked each step, scored only if the same id stayed
in-band before+after). Residual = row's visual delta-top minus the
scroll delta: 0 == smooth. Gate is peak <=2px, rms <=0.6px.
Validity: within a single cold run the already-realized rows read
residual 0.0 exactly while realizing rows drift -27..-75px — an artifact
would drift on both. Negative sign shows the estimator over-reserves.
At tip: peak 75px, rms 40px over 23 steps → RED. A correct fill of
scrollTop absorbs the drift into the scroll delta, driving residual->0.
Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>