Skip to content

artifact-canvas: horizontal mode wheel/trackpad should page one column instantly (snap), not glide #1701

Description

@amrmelsayed

Goal

In the artifact canvas's horizontal reading mode, wheel and trackpad input should page one column at a time, instantly, instead of gliding the text. Continuously moving text is the cognitive cost the owner wants removed: the reader should see a still column, then the next still column, the way a paged e-reader turns pages.

Today

packages/artifact-canvas/src/components/ArtifactCanvas.tsx, wheel effect: vertical wheel deltas accumulate into a pixel target and a requestAnimationFrame loop eases the scroll position toward it (30% per frame). There is no quantisation, so the view can stop anywhere, including mid-column. The glide was added at dev-approval on spec 1380 because intercepting the wheel bypassed the browser's own animation and a notched mouse felt jagged at 120px per event.

Keyboard paging already snaps: pageColumn quantises to the measured column grid and sets scrollLeft instantly. Minimap and marker jumps use smooth scroll to centre a block.

Change

Route wheel gestures through the existing pageColumn primitive instead of the glide.

Gesture rules (the only real design work):

  1. One gesture, one column. Accumulate deltaY (normalised via the existing wheelDeltaPx). When the running total crosses a small threshold (about a third of a mouse notch, ~40px), call pageColumn(body, sign) once and latch.
  2. Latch until the stream goes quiet. Ignore further events until no wheel event has arrived for ~150ms. This absorbs a trackpad's inertial tail (which can run 1-2s) so one swipe moves exactly one column. A notched mouse emits discrete clicks, so each click is its own gesture and pages one column.
  3. Direction reversal resets the latch so a quick back-swipe works immediately.
  4. Pass-through rules unchanged: ctrl/meta-modified wheels (pinch zoom), horizontal-dominant deltas (native trackpad gesture), and events an inner vertical scroller (capped code block, table, card, composer) can still consume.
  5. No animation. The step is instant, as pageColumn already is. prefers-reduced-motion therefore needs no special case on this path. Remove the glide loop and cancelWheelGlideRef (paging no longer has a glide to cancel).

Out of scope: a screenful step for PageDown/Space vs one column for arrows (a separate improvement suggested by the Monash 2009 reading strategies); justification; column height caps.

Tests

  • Rewrite the wheel decision-table tests in packages/artifact-canvas/src/__tests__/ around gestures: a single notch pages one column; a burst of 30 small deltas within 150ms pages one column; a burst followed by a 200ms gap then another burst pages two; reversal mid-burst pages back; the four pass-through cases leave scrollLeft untouched; preventDefault still fires on consumed events (no residual vertical scroll).
  • Browser check (Playwright fixture from 1380): mouse wheel and trackpad simulation land on column starts every time; ReadingProgress readout increments by exactly one per gesture.

Verification by the owner

Notched mouse: one click per column, no stutter. Trackpad: one swipe per column, inertia does not skip. Confirm the jaggedness complaint from the 1380 dev-approval does not apply to whole-column jumps.

Relation

  • Spec 1380 Constraint 5 (wheel remap): amend the wording from "vertical wheel becomes horizontal scroll" to "vertical wheel pages one column"; record the decision in the spec.
  • Keyboard paging and jump behaviour unchanged.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/vscodeArea: VS Code extension

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions