Skip to content

fix(ui): preserve nested scroll gesture ownership - #688

Merged
pascalandr merged 2 commits into
devfrom
fix/nested-scroll-input-ownership
Sep 10, 2026
Merged

pascalandr merged 2 commits into
devfrom
fix/nested-scroll-input-ownership

Conversation

@pascalandr

Copy link
Copy Markdown
Contributor

Summary

Follow up on the MMB, wheel and keyboard scrolling regressions reported after #683.

  • Keep middle-button drags on the scrollers selected at pointerdown until release, even when the pointer leaves their bounds. Resolve horizontal and vertical owners independently for wide code nested inside a vertically scrolling shell.
  • Keep a continuous vertical wheel gesture on its starting scroller so a shell passing under a stationary pointer cannot steal it. Allow ancestor chaining at an edge; leave horizontal/Shift-wheel, zoom and uncancellable events to the browser.
  • Replace an outstanding Virtua imperative scroll only once on user intent instead of issuing scrollBy(0) on every wheel/key event and creating another measurement-time pin.
  • Leave navigation keys with a nested scroller that can consume them, and respect events already prevented by descendant controls.
  • End captured MMB gestures on release, cancellation, lost capture, blur, hidden/detached content or cleanup. Preserve normal link, editor and control behavior.

Review and regressions

Review identified three additional defects, each reproduced by a failing browser test before correction:

  1. Horizontal code could swallow vertical MMB movement intended for the containing shell.
  2. Hiding a session did not terminate its captured MMB gesture.
  3. A prevented Home event could still navigate the transcript.

The subsequent scoped review identified no remaining actionable findings. Existing MMB tests now drive actual mouse movement rather than writing scrollTop to simulate the drag. Tests exercise the real Solid virtual list/follow controllers and a real ToolCall fixture.

Validation

Validated source: 5b1926cf8e9464a8828ff68ec33852ca94567950.

  • 43/43 Chromium browser tests, in two complete runs.
  • 57/57 focused virtual-scroll behavior, measurement and reader-settlement tests.
  • UI and Electron typechecks.
  • Windows Tauri release build (--no-bundle).
  • 14 targeted checks in the rebuilt Tauri/WebView2 application: both MMB starting zones, release, stationary-cursor wheel routing across a passing shell, six navigation keys in a focused shell, and repeated transcript Arrow/Page keys.
  • Verified that the loaded source maps match the reviewed source files; captured native screenshot evidence.
  • git diff --check.

Native release executable SHA-256: BC2EDF02138440691008DD1E1F4B28EF12E5C76555F681D299D6ED8827013735.

These are targeted checks, not a claim of exhaustive desktop or cross-platform coverage. An initial native test run lost its target DOM element; the completed-shell-targeted rerun passed all 14 checks. The user's separate UI #667 executable was restored unchanged after validation; no UI-worktree changes are included here. GitHub CI remains separate from these local checks.

Scope / maintenance

Only four files change. No preferences, translations, dependencies or native-host implementation changes. packages/ui/src/components/virtual-follow-list.tsx is an existing oversized file (~1,188 lines); the gesture routing is isolated in a focused helper rather than adding a general refactor.

Keep middle-button drags on the scrollers selected at pointerdown rather
than depending on host-specific native autoscroll. Resolve horizontal and
vertical owners independently so a wide code block cannot swallow vertical
movement intended for its containing shell. Release capture and animation
on pointer termination, blur, hidden/detached content, or component cleanup;
leave links, editors and interactive controls to their normal handlers.

Latch vertical wheel sequences until their idle boundary so an output
passing under a stationary pointer cannot steal the transcript's gesture.
Allow ancestor chaining at an edge and leave zoom, Shift-wheel, horizontal
and uncancellable events to the browser. Notify existing follow controllers
before applying redirected motion.

Replace Virtua's outstanding imperative scroll only once on user intent:
unconditional scrollBy(0) on each wheel/key event itself creates a new
measurement-time pin. Keep nested keyboard navigation in its scroller and
respect keys already consumed by descendant controls.

Replace simulated MMB scrollTop writes with actual browser mouse movement.
Add real ToolCall fixtures and regression coverage for pointer target
crossings, release, streaming appends/window shifts, wheel handoff, repeated
navigation keys, independent axes, hidden panes and prevented Home. The
three review findings were reproduced before their fixes and re-reviewed.

Validation: 43 Chromium regressions pass in two full runs, 57 focused
virtual-scroll tests pass, and UI/Electron typechecks pass. The rebuilt
Windows Tauri release passes 14 targeted WebView2 checks for both MMB
owners, release, passing-shell wheel routing, nested navigation and repeated
transcript keys. Loaded source maps match the reviewed source files. This
is targeted validation, not exhaustive desktop or cross-platform coverage.
@pascalandr
pascalandr merged commit ca04bff into dev Sep 10, 2026
2 checks passed
@pascalandr
pascalandr deleted the fix/nested-scroll-input-ownership branch September 10, 2026 08:50
@github-actions

Copy link
Copy Markdown

PR builds are available as GitHub Actions artifacts:

https://github.com/NeuralNomadsAI/CodeNomad/actions/runs/34457348610

Artifacts expire in 7 days.
Artifacts:

  • pr-688-02ca7d7577554742e88628b554b65230baa48cc7-tauri-windows
  • pr-688-02ca7d7577554742e88628b554b65230baa48cc7-tauri-macos
  • pr-688-02ca7d7577554742e88628b554b65230baa48cc7-electron-macos
  • pr-688-02ca7d7577554742e88628b554b65230baa48cc7-tauri-macos-arm64
  • pr-688-02ca7d7577554742e88628b554b65230baa48cc7-electron-linux
  • pr-688-02ca7d7577554742e88628b554b65230baa48cc7-tauri-linux
  • pr-688-02ca7d7577554742e88628b554b65230baa48cc7-electron-windows

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