[number field] Prevent scrubbing on horizontal wheel events - #5463
Conversation
|
@claude review |
PR reviewThe one-line guard fixes the obvious case (a pure horizontal wheel no longer increments the field) but keys off Bugs (2)1. 🔴 Shift + wheel stepping by
|
commit: |
Bundle size
PerformanceTotal duration: 1,053.07 ms -38.15 ms(-3.5%) | Renders: 76 (+0) | Paint: 1,667.07 ms -41.45 ms(-2.4%) No significant changes — details Check out the code infra dashboard for more information about this PR. |
✅ Deploy Preview for base-ui ready!Built without sensitive environment variables
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
@claude review |
PR reviewThe core fix is sound: pure and noisy horizontal wheel gestures now fall through to the page instead of scrubbing, and the axis-dominance comparison is the right shape for touchpad noise. Nothing here is merge-blocking, but the Shift path applies the same noise reasoning inconsistently — the delta axis is picked by Bugs (1)1. 🟠 Shift-held horizontal swipe picks its direction from sub-pixel cross-axis noiseLocation: const delta = event.deltaY !== 0 || !event.shiftKey ? event.deltaY : event.deltaX;
const isHorizontalGesture =
!event.shiftKey && Math.abs(event.deltaX) > Math.abs(event.deltaY);The new comment on Failure scenario: Fix: derive both the axis choice and the filter from the same dominance test, which is also less code: // Some browsers deliver shift + wheel on the horizontal axis, so there the horizontal
// delta is the intended vertical one. Touchpads emit sub-pixel noise on the cross axis,
// so compare the axes rather than requiring an exact zero.
const isHorizontal = Math.abs(event.deltaX) > Math.abs(event.deltaY);
const delta = event.shiftKey && isHorizontal ? event.deltaX : event.deltaY;
// Ignore horizontal gestures so the page can scroll instead of scrubbing. Shift is exempt:
// its gesture is horizontal wherever the browser swaps the axis.
if (delta === 0 || (!event.shiftKey && isHorizontal)) {
return;
}This keeps all five wheel cases the PR adds passing ( Tests (1)1. 🟡 New wheel tests never assert the scrubbing path is still canceled, and skip the Shift + noise caseLocation: // `fireEvent` returns false when the event was canceled with `preventDefault`.
expect(fireEvent.wheel(input, { deltaY: 0, deltaX: 100 })).toBe(true);The Failure scenario: Removing Fix: add VerdictApprove after nits — the horizontal-gesture filter is correct for the non-Shift case; the Shift branch's exact-zero axis test should be aligned with the dominance test before merge, and it shortens the code. 🤖 Review generated with Claude Code · Opus 5 (High) · |
There was a problem hiding this comment.
Pull request overview
This PR fixes an issue in Base UI’s NumberField wheel-scrubbing behavior where horizontal-dominant wheel gestures (e.g., trackpad sideways swipes or tilt wheels) could unintentionally step and commit the value while also preventing page scroll. It updates the wheel handler to ignore horizontal gestures, while still supporting browser-specific axis swapping when Shift is held.
Changes:
- Ignore horizontal-dominant wheel gestures so they don’t scrub (and don’t call
preventDefault), allowing the page to scroll normally. - When
Shiftis held and the browser swaps wheel axes, treat the horizontal delta as the intended “vertical” delta for scrubbing direction. - Add/extend tests covering horizontal gestures, cross-axis noise, and
Shift+ swapped-axis behavior.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| packages/react/src/number-field/root/NumberFieldRoot.tsx | Adds axis-dominance detection and uses an appropriate delta for wheel scrubbing direction while ignoring horizontal gestures. |
| packages/react/src/number-field/root/NumberFieldRoot.test.tsx | Adds coverage to ensure horizontal wheel events don’t scrub (and don’t cancel scrolling) and verifies Shift + swapped-axis behavior. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Cover horizontal and zero-delta wheel events being ignored, vertical events still being canceled, and shift + wheel stepping by largeStep on the swapped axis regardless of cross-axis noise.
Wheel scrub treated any event with no vertical delta as an increment, so horizontal trackpad swipes and tilt wheels silently stepped and committed the value while blocking the page scroll. Ignore horizontal-dominant gestures, and use the horizontal delta when shift is held.