Skip to content

feat(fresh-ui): give the wheel an axis - #3032

Merged
sinelaw merged 1 commit into
masterfrom
claude/fresh-ui-wheel-axis
Aug 19, 2026
Merged

feat(fresh-ui): give the wheel an axis#3032
sinelaw merged 1 commit into
masterfrom
claude/fresh-ui-wheel-axis

Conversation

@sinelaw

@sinelaw sinelaw commented Aug 19, 2026

Copy link
Copy Markdown
Owner

Base of a two-PR stack. #3028 (the fresh-editor UI migration) is stacked on top of this.

Why

The scroll model has always been two-dimensional — a viewport's offset and its maximum are both Points, and ViewportProps::scroll is a pair — but nothing could address the horizontal one. Input::Wheel carried a bare scalar and scroll_chain only ever moved y. The axis was implied by the geometry everywhere except where it could be driven.

This surfaced while writing the editor-side input adapter for the migration: translating a horizontal wheel had no target, so the adapter had to decline it and leave it on the legacy path. Rather than encode that gap as an editor workaround — which is the class of thing the migration exists to remove — it is closed here, in the library, before anything depends on it.

What changed

  • Axis::{Vertical, Horizontal}, carried on Input::Wheel and on the Event a Wheel listener receives, so a widget that scrolls itself can tell the two apart instead of guessing.
  • scroll_chain moves and clamps the axis it was given.
  • The wheel travels through propagation as one parameter (Wheel { delta, axis }) rather than two, so the gestures that are not wheels pass Wheel::NONE instead of a bare 0 whose meaning had to be inferred at each call site.

What this deliberately does not do

It does not make the built-in Viewport scroll sideways. A viewport lays its child out under Constraints::new(0, w, ..), bounding it to the window's own width, so content can never overflow horizontally and that maximum stays zero — Viewport is a vertical scroller by construction, and remains one here.

A horizontally scrollable viewport is a separate feature, and nothing needs it yet: a host leaf that scrolls its own content (an editor buffer) does that itself and only needs the axis to reach its handler intact. a_viewport_has_no_horizontal_extent_to_scroll pins that boundary, so if someone later builds a horizontal viewport, the test says what changed.

Verification

tests/pointer.rs covers all three cases: a Wheel listener sees the axis; a vertical wheel still moves only y; a horizontal wheel over a viewport correctly does nothing rather than scrolling the wrong way.

Full suite green — 150 tests, goldens included, so no rendered output moved. The crate still builds standalone with unicode-width as its only runtime dependency.


Generated by Claude Code

The scroll model has always been two-dimensional — a viewport's offset
and its maximum are both `Point`s, and `ViewportProps::scroll` is a
pair — but nothing could address the horizontal one: `Input::Wheel`
carried a bare scalar and `scroll_chain` only ever moved `y`. The axis
was implied by the geometry everywhere except where it could be driven.

- `Axis::{Vertical, Horizontal}`, carried on `Input::Wheel` and on the
  `Event` a `Wheel` listener receives, so a widget that scrolls itself
  can tell the two apart instead of guessing.
- `scroll_chain` moves and clamps the axis it was given.
- The wheel is one parameter (`Wheel { delta, axis }`) through
  propagation rather than two, so the gestures that are not wheels pass
  `Wheel::NONE` instead of a bare zero whose meaning had to be inferred.

What this does NOT do is make the built-in `Viewport` scroll sideways.
A viewport lays its child out under `Constraints::new(0, w, ..)`,
bounding it to the window's own width, so content never overflows
horizontally and that maximum stays zero: `Viewport` is a vertical
scroller by construction, and remains one. A horizontally scrollable
viewport is a separate feature, and nothing needs it yet — a host leaf
that scrolls its own content (an editor buffer) does that itself, and
only needs the axis to reach its handler intact.

`tests/pointer.rs` pins all three: the listener sees the axis, a
vertical wheel still moves only `y`, and a horizontal wheel over a
viewport correctly does nothing rather than scrolling the wrong way.
The golden tests are unchanged, so no rendered output moved.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ws2GtzEBQRFZMv8qF61Jzr
@sinelaw
sinelaw merged commit 3431e0a into master Aug 19, 2026
9 of 10 checks passed
@sinelaw
sinelaw deleted the claude/fresh-ui-wheel-axis branch August 19, 2026 06:15
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.

2 participants