fix: add desktop drag scrolling for horizontal rows#98
Conversation
WalkthroughA new composable hook Changes
Sequence Diagram(s)sequenceDiagram
actor User
participant Component as Vue Component
participant Composable as useDesktopHorizontalScroll
participant EventSystem as Event Listeners
User->>EventSystem: Move mouse/wheel on element
EventSystem->>Composable: Trigger wheel/pointer events
Composable->>Composable: Track drag state (position, threshold)
Composable->>Composable: Calculate scroll offset
Composable->>Component: Update container scrollLeft
Component->>Component: Re-render with new scroll position
Component-->>User: Display updated scroll view
User->>EventSystem: Click after drag
EventSystem->>Composable: pointerup/click event
Composable->>EventSystem: Suppress click if drag occurred
EventSystem-->>User: Click action prevented
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes 🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
✨ Simplify code
📝 Coding Plan
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@composables/useDesktopHorizontalScroll.ts`:
- Around line 20-41: Update the wheel handler in useDesktopHorizontalScroll (the
function that checks isLikelyMouseWheel and currently does
event.preventDefault() before horizontal scrolling) to early-return when the
wheel is being used as a zoom gesture by checking event.ctrlKey (and optionally
event.metaKey for macOS); add this check to the existing early-return
condition(s) so zoom (Ctrl+wheel) is not blocked before calling
event.preventDefault() and the horizontal scroll logic.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 1423d4cc-d47c-4103-b8ad-2adfa605e56e
📒 Files selected for processing (3)
components/pages/home/FeaturedTags.vuecomponents/pages/posts/navigation/search/SearchMenu.vuecomposables/useDesktopHorizontalScroll.ts
| // Preserve touchpad/native horizontal behavior and only map normal mouse wheel. | ||
| if (event.deltaX !== 0 || event.deltaY === 0 || !isLikelyMouseWheel(event)) { | ||
| return | ||
| } | ||
|
|
||
| const maxScrollLeft = scrollContainer.scrollWidth - scrollContainer.clientWidth | ||
|
|
||
| if (maxScrollLeft <= 0) { | ||
| return | ||
| } | ||
|
|
||
| const canScrollLeft = scrollContainer.scrollLeft > 0 | ||
| const canScrollRight = scrollContainer.scrollLeft < maxScrollLeft | ||
|
|
||
| if ((event.deltaY < 0 && !canScrollLeft) || (event.deltaY > 0 && !canScrollRight)) { | ||
| return | ||
| } | ||
|
|
||
| event.preventDefault() | ||
|
|
||
| scrollContainer.scrollLeft += event.deltaY | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
In browser wheel event handling, does preventDefault() on a wheel event with ctrlKey=true suppress page zoom behavior?
💡 Result:
Yes—when the wheel event is cancelable and your listener is non-passive, calling event.preventDefault() on a wheel event with ctrlKey === true suppresses the browser’s default page-zoom (Ctrl+wheel / trackpad-pinch-zoom) behavior. MDN notes that zoom gestures fire wheel events with ctrlKey set, and that canceling the event prevents “scrolling or zooming.” [1]
Practical requirements / caveats:
- Register the listener with
{ passive: false }, otherwise the browser may ignorepreventDefault()for performance reasons. [1] - Some browsers may make only the first event in a wheel sequence cancelable (later events can be non-cancelable), and non-cancelable events can’t be prevented. [1], [2]
- Chromium explicitly changed behavior so Ctrl+wheel goes to the page first and only triggers browser zoom if unhandled (i.e., not prevented). [3]
Sources: [1] MDN wheel event docs, [2] W3C Wheel Events spec, [3] Chromium blink-dev “ctrl+mousewheel events can now be overridden”.
🏁 Script executed:
fd -t f "useDesktopHorizontalScroll.ts"Repository: Rule-34/App
Length of output: 96
🏁 Script executed:
cat -n composables/useDesktopHorizontalScroll.tsRepository: Rule-34/App
Length of output: 4317
Add early return for zoom gestures (Ctrl+wheel) in wheel handler.
The wheel event listener at line 113 is registered with { passive: false }, which means event.preventDefault() at line 38 will effectively suppress browser default behavior. Without checking event.ctrlKey first, this prevents page zoom when using Ctrl+wheel. Add a check for zoom gestures to the early return condition:
Proposed patch
// Preserve touchpad/native horizontal behavior and only map normal mouse wheel.
- if (event.deltaX !== 0 || event.deltaY === 0 || !isLikelyMouseWheel(event)) {
+ if (event.ctrlKey || event.deltaX !== 0 || event.deltaY === 0 || !isLikelyMouseWheel(event)) {
return
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // Preserve touchpad/native horizontal behavior and only map normal mouse wheel. | |
| if (event.deltaX !== 0 || event.deltaY === 0 || !isLikelyMouseWheel(event)) { | |
| return | |
| } | |
| const maxScrollLeft = scrollContainer.scrollWidth - scrollContainer.clientWidth | |
| if (maxScrollLeft <= 0) { | |
| return | |
| } | |
| const canScrollLeft = scrollContainer.scrollLeft > 0 | |
| const canScrollRight = scrollContainer.scrollLeft < maxScrollLeft | |
| if ((event.deltaY < 0 && !canScrollLeft) || (event.deltaY > 0 && !canScrollRight)) { | |
| return | |
| } | |
| event.preventDefault() | |
| scrollContainer.scrollLeft += event.deltaY | |
| } | |
| // Preserve touchpad/native horizontal behavior and only map normal mouse wheel. | |
| if (event.ctrlKey || event.deltaX !== 0 || event.deltaY === 0 || !isLikelyMouseWheel(event)) { | |
| return | |
| } | |
| const maxScrollLeft = scrollContainer.scrollWidth - scrollContainer.clientWidth | |
| if (maxScrollLeft <= 0) { | |
| return | |
| } | |
| const canScrollLeft = scrollContainer.scrollLeft > 0 | |
| const canScrollRight = scrollContainer.scrollLeft < maxScrollLeft | |
| if ((event.deltaY < 0 && !canScrollLeft) || (event.deltaY > 0 && !canScrollRight)) { | |
| return | |
| } | |
| event.preventDefault() | |
| scrollContainer.scrollLeft += event.deltaY | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@composables/useDesktopHorizontalScroll.ts` around lines 20 - 41, Update the
wheel handler in useDesktopHorizontalScroll (the function that checks
isLikelyMouseWheel and currently does event.preventDefault() before horizontal
scrolling) to early-return when the wheel is being used as a zoom gesture by
checking event.ctrlKey (and optionally event.metaKey for macOS); add this check
to the existing early-return condition(s) so zoom (Ctrl+wheel) is not blocked
before calling event.preventDefault() and the horizontal scroll logic.
Summary
Validation
Feedback issue: https://feedback.r34.app/posts/270/feature-scroll-horizontally-on-desktop-by-click-dragging-or-with-scrolling
Summary by CodeRabbit