LearnNewsExamplesServices
Frontmatter
id12906
titleOverdrag scrolling never updates the SortZone scroll term — post-scroll drag math corrupts
stateClosed
labels
bugairegressiongrid
assigneesneo-fable
createdAtJun 11, 2026, 5:20 PM
updatedAtJun 11, 2026, 9:16 PM
githubUrlhttps://github.com/neomjs/neo/issues/12906
authorneo-fable
commentsCount1
parentIssue12883
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[]
closedAtJun 11, 2026, 9:16 PM

Overdrag scrolling never updates the SortZone scroll term — post-scroll drag math corrupts

Closed v13.0.0/archive-v13-0-0-chunk-17 bugairegressiongrid
neo-fable
neo-fable commented on Jun 11, 2026, 5:20 PM

Context

Sub-issue of #12883. Operator manual repro on merged dev (post #12901 trace instrumentation), full-tail trace captured live from his session: dragging a column right until auto-scroll engages, then dragging back, produces (a) body cells that stop updating and (b) header cells moving wrongly. The trace convicts one mechanism for both.

Release classification: parent #12883 carries the v13 board gate; this sub is its PR-deliverable leaf.

The Problem

Trace evidence (operator session, single drag of privateContributionsRatio):

  1. Seven scroll events fire (the engine auto-scrolls ~6 columns; the container physically moves) — and sl: 0 on every event in the entire trace. The zone's scroll-correction term (me.scrollLeft, consumed by the move-delta math delta = clientX - ownerX + me.scrollLeft - offsetX - itemRects[i].left) never updates.
  2. The moment the drag returns in-bounds, deltas read d: -812, -769, -700, … (pointer at viewport ~1276 vs full-span slot positions 1586+ with zero correction) → an avalanche of wrong switches, index 16→0 in ~250ms — the operator's "header cells do not move correctly".
  3. The same uncorrected coordinates drive switchItems' body-cell/columnPositions writes mid-scroll while the engine's scroll-triggered re-pooling rebuilds rows — two write paths in different coordinate spaces — the operator's "body cells do not update".

The Architectural Reality

  • Normal horizontal scroll-sync runs through the GridHorizontalScrollSync main-thread addon, registered against the dedicated horizontalScrollbar element (grid.ScrollManager#updateGridHorizontalScrollSyncAddon); grid.header.Toolbar#afterSetScrollLeft then pushes into sortZone.scrollLeft.
  • The drag's overdrag path scrolls via grid.header.Toolbar#scrollToIndexNeo.main.DomAccess.scrollIntoView — a programmatic native scroll of the grid container, invisible to that pipeline. Nothing writes the zone's term.
  • Semantics note: the zone's scrollLeft is scroll-since-drag-start (the drag-start itemRects snapshot bakes in any pre-existing scroll), so the correct source is the owner toolbar's viewport-x shift relative to the drag-start ownerRect.x — not the absolute container scrollLeft.

The Fix

  1. draggable.container.SortZone#scrollToIndex: after the owner scroll completes, re-measure the owner's rect and set me.scrollLeft = me.ownerRect.x - liveOwnerRect.x (the viewport shift = scroll-since-start, by construction).
  2. Reset scrollLeft: 0 at drag start and in the drag-end state reset (it currently leaks across drags).
  3. Whitebox-e2e repro (operator-proposed): a spec driving overdrag + drag-back via page.mouse, asserting through the drag trace — sl > 0 after scroll events, no switch avalanche (bounded switch count for the gesture), and post-drop header/body agreement. Requires a small fixture passthrough for getDragTrace.

Acceptance Criteria

  • After overdrag scrolling, trace move events carry sl equal to the scrolled amount (non-zero).
  • Dragging back in-bounds after a scroll produces NO avalanche (switches follow the pointer; deltas bounded by pointer movement).
  • Body cells and headers agree during and after the scroll+return gesture (within-region drop lands where the pointer indicates).
  • Whitebox-e2e spec covers the gesture end-to-end via trace assertions and passes.
  • scrollLeft does not leak across drags (second drag starts at 0).

Out of Scope

  • Mid-drag user wheel-scrolling (the toolbar's absolute-value push into the zone's relative term is a pre-existing space mismatch; separate ticket if it bites).
  • The locked-start-region drag never engaging overdrag at all (separate gap, logged during this investigation).

Related

  • Parent: #12883 · Trace instrumentation that enabled the conviction: #12901/#12902 · Fixture identity-bind: #12897

Live latest-open sweep: checked latest open issues at 2026-06-11T15:30Z; no equivalent found.

Origin Session ID: e605ce21-3668-445c-bc00-45896aa9a092

Retrieval Hint: "overdrag scrollLeft sl zero avalanche switches scroll-since-drag-start"

tobiu referenced in commit b1401a8 - "fix: route column-drag overdrag scrolling through the scrollbar pipeline (#12906) (#12908) on Jun 11, 2026, 9:16 PM
tobiu closed this issue on Jun 11, 2026, 9:16 PM