History

fix: attach wheel handler with { passive: false } to enable preventDefault

React 17+ registers onWheel handlers as passive by default, making event.preventDefault() a no-op. This caused vertical-to-horizontal scroll conversion on the turn chip strip to fail silently. Replaced the React onWheel JSX prop with a useEffect that attaches the handler via addEventListener('wheel', handler, { passive: false }) on the ref element directly.

Cursor Agent committed 8 months ago

Commit 9bf6ec71 parent f3b773f1 file · +7 −13Browse files

Unified · Split

apps/web/src/components/DiffPanel.tsx+7−13
@@ -8,15 +8,7 @@ import { · 7 unmodified lines
88 import { useQuery } from "@tanstack/react-query";
99 import { useParams } from "@tanstack/react-router";
1010 import { ChevronLeftIcon, ChevronRightIcon, Columns2Icon, Rows3Icon } from "lucide-react";
11−import {
12− type ReactNode,
13− type WheelEvent as ReactWheelEvent,
14− useCallback,
15− useEffect,
16− useMemo,
17− useRef,
18− useState,
19−} from "react";
11+import { type ReactNode, useCallback, useEffect, useMemo, useRef, useState } from "react";
2012 import { checkpointDiffQueryOptions } from "~/lib/providerReactQuery";
2113 import { cn } from "~/lib/utils";
2214 import { isElectron } from "../env";
@@ -92,7 +84,8 @@ interface DiffPanelProps { · 69 unmodified lines
9284
9385 export function DiffWorkerPoolProvider({ children }: { children?: ReactNode }) {
9486 const workerPoolSize = useMemo(() => {
95− const cores = typeof navigator === "undefined" ? 4 : Math.max(1, navigator.hardwareConcurrency || 4);
87+ const cores =
88+ typeof navigator === "undefined" ? 4 : Math.max(1, navigator.hardwareConcurrency || 4);
9689 return Math.max(2, Math.min(6, Math.floor(cores / 2)));
9790 }, []);
9891
@@ -265,7 +258,7 @@ export default function DiffPanel({ mode = "inline" }: DiffPanelProps) { · 166 unmodified lines
265258 if (!element) return;
266259 element.scrollBy({ left: offset, behavior: "smooth" });
267260 }, []);
268− const onTurnStripWheel = useCallback((event: ReactWheelEvent<HTMLDivElement>) => {
261+ const onTurnStripWheel = useCallback((event: WheelEvent) => {
269262 const element = turnStripRef.current;
270263 if (!element) return;
271264 if (element.scrollWidth <= element.clientWidth + 1) return;
@@ -282,15 +275,17 @@ export default function DiffPanel({ mode = "inline" }: DiffPanelProps) { · 10 unmodified lines
282275 updateTurnStripScrollState();
283276 const onScroll = () => updateTurnStripScrollState();
284277 element.addEventListener("scroll", onScroll, { passive: true });
278+ element.addEventListener("wheel", onTurnStripWheel, { passive: false });
285279
286280 const resizeObserver = new ResizeObserver(() => updateTurnStripScrollState());
287281 resizeObserver.observe(element);
288282
289283 return () => {
290284 element.removeEventListener("scroll", onScroll);
285+ element.removeEventListener("wheel", onTurnStripWheel);
291286 resizeObserver.disconnect();
292287 };
293− }, [updateTurnStripScrollState]);
288+ }, [updateTurnStripScrollState, onTurnStripWheel]);
294289
295290 useEffect(() => {
296291 updateTurnStripScrollState();
@@ -359,7 +354,6 @@ export default function DiffPanel({ mode = "inline" }: DiffPanelProps) { · 62 unmodified lines
359354 <div
360355 ref={turnStripRef}
361356 className="turn-chip-strip flex gap-1 overflow-x-auto px-8 py-0.5"
362− onWheel={onTurnStripWheel}
363357 >
364358 <button
365359 type="button"