diff --git a/CHANGELOG.md b/CHANGELOG.md index 442f93f..550d6df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ All notable user-visible changes to Hunk are documented in this file. ### Fixed +- Smoothed mouse-wheel review scrolling so small diffs stay precise while sustained wheel gestures still speed up. + ## [0.9.4] - 2026-04-14 ### Added diff --git a/src/ui/components/panes/DiffPane.tsx b/src/ui/components/panes/DiffPane.tsx index 479a9cc..9c1b6b4 100644 --- a/src/ui/components/panes/DiffPane.tsx +++ b/src/ui/components/panes/DiffPane.tsx @@ -16,6 +16,7 @@ import { measureDiffSectionGeometry, type DiffSectionGeometry, } from "../../lib/diffSectionGeometry"; +import { createReviewMouseWheelScrollAcceleration } from "../../lib/scrollAcceleration"; import { buildFileSectionLayouts, buildInStreamFileHeaderHeights, @@ -182,6 +183,10 @@ export function DiffPane({ onViewportCenteredHunkChange?: (fileId: string, hunkIndex: number) => void; }) { const renderer = useRenderer(); + const mouseWheelScrollAcceleration = useMemo( + () => createReviewMouseWheelScrollAcceleration(), + [], + ); const adjacentPrefetchFileIds = useMemo( () => buildAdjacentPrefetchFileIds(files, selectedFileId), @@ -977,7 +982,7 @@ export function DiffPane({ suppressViewportSelectionSync, ]); - // Configure scroll step size to scroll exactly 1 line per step + // Keep keyboard step scrolling at exactly one row while wheel scrolling uses its own multiplier. useEffect(() => { const scrollBox = scrollRef.current; if (scrollBox) { @@ -1020,6 +1025,7 @@ export function DiffPane({ viewportCulling={true} focused={pagerMode} onMouseScroll={handleMouseScroll} + scrollAcceleration={mouseWheelScrollAcceleration} rootOptions={{ backgroundColor: theme.panel }} wrapperOptions={{ backgroundColor: theme.panel }} viewportOptions={{ backgroundColor: theme.panel }} diff --git a/src/ui/lib/scrollAcceleration.ts b/src/ui/lib/scrollAcceleration.ts new file mode 100644 index 0000000..cdd6160 --- /dev/null +++ b/src/ui/lib/scrollAcceleration.ts @@ -0,0 +1,15 @@ +import { MacOSScrollAccel, type ScrollAcceleration } from "@opentui/core"; + +/** + * Keep the first wheel tick precise, then ramp up during sustained bursts. + * + * This matches the general pattern used by terminal UIs better than scaling by total diff size: + * short diffs stay controllable, while long repeated wheel gestures still speed up. + */ +export function createReviewMouseWheelScrollAcceleration(): ScrollAcceleration { + return new MacOSScrollAccel({ + A: 0.4, + tau: 4, + maxMultiplier: 3, + }); +}