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):
- 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.
- 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.
- Direction reversal resets the latch so a quick back-swipe works immediately.
- 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.
- 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.
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:
pageColumnquantises to the measured column grid and setsscrollLeftinstantly. Minimap and marker jumps use smooth scroll to centre a block.Change
Route wheel gestures through the existing
pageColumnprimitive instead of the glide.Gesture rules (the only real design work):
deltaY(normalised via the existingwheelDeltaPx). When the running total crosses a small threshold (about a third of a mouse notch, ~40px), callpageColumn(body, sign)once and latch.pageColumnalready is.prefers-reduced-motiontherefore needs no special case on this path. Remove the glide loop andcancelWheelGlideRef(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
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 leavescrollLeftuntouched;preventDefaultstill fires on consumed events (no residual vertical scroll).ReadingProgressreadout 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