From bcbd4b68e91a828a687d9fc71fc7b172d2263e0d Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 21 May 2026 03:59:29 +0000 Subject: [PATCH] fix: replace mouse events with pointer events in ImageDiffViewer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaces onMouseDown/mousemove/mouseup with the Pointer Events API so that the slider and pan interactions work on touch screens and trackpads, not just mouse input. Changes: - onSliderMouseDown → onSliderPointerDown (React.PointerEvent) - onPanMouseDown → onPanPointerDown, guards on pointerType instead of button - Global mousemove/mouseup listeners → pointermove/pointerup - setPointerCapture on drag start to keep events routed correctly - touch-action: none on draggable elements to prevent browser scroll interference Closes #20 https://claude.ai/code/session_01VLHEkn9xkvhAhyRYHRrtFw --- .../src/components/shared/ImageDiffViewer.tsx | 37 +++++++++++-------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/wimygit-tauri/src/components/shared/ImageDiffViewer.tsx b/wimygit-tauri/src/components/shared/ImageDiffViewer.tsx index 074cd4a..22cdb55 100644 --- a/wimygit-tauri/src/components/shared/ImageDiffViewer.tsx +++ b/wimygit-tauri/src/components/shared/ImageDiffViewer.tsx @@ -147,22 +147,24 @@ export function ImageDiffViewer({ beforeSrc, afterSrc, filename, mode }: ImageDi }, [mode, applyWheelZoom]); // Slider handle drag - const onSliderMouseDown = useCallback((e: React.MouseEvent) => { + const onSliderPointerDown = useCallback((e: React.PointerEvent) => { e.preventDefault(); e.stopPropagation(); + e.currentTarget.setPointerCapture(e.pointerId); sliderDragging.current = true; }, []); // Pan drag - const onPanMouseDown = useCallback((e: React.MouseEvent) => { - if (e.button !== 0) return; + const onPanPointerDown = useCallback((e: React.PointerEvent) => { + if (e.pointerType === "mouse" && e.button !== 0) return; e.preventDefault(); + e.currentTarget.setPointerCapture(e.pointerId); panDragging.current = true; setIsPanDragging(true); panStart.current = { mouseX: e.clientX, mouseY: e.clientY, panX: panOffset.x, panY: panOffset.y }; }, [panOffset.x, panOffset.y]); - const onMouseMove = useCallback((e: MouseEvent) => { + const onPointerMove = useCallback((e: PointerEvent) => { if (sliderDragging.current && containerRef.current) { const rect = containerRef.current.getBoundingClientRect(); setSliderPct(Math.min(100, Math.max(0, ((e.clientX - rect.left) / rect.width) * 100))); @@ -174,7 +176,7 @@ export function ImageDiffViewer({ beforeSrc, afterSrc, filename, mode }: ImageDi } }, []); - const onMouseUp = useCallback(() => { + const onPointerUp = useCallback(() => { sliderDragging.current = false; if (panDragging.current) { panDragging.current = false; @@ -184,13 +186,13 @@ export function ImageDiffViewer({ beforeSrc, afterSrc, filename, mode }: ImageDi }, []); useEffect(() => { - window.addEventListener("mousemove", onMouseMove); - window.addEventListener("mouseup", onMouseUp); + window.addEventListener("pointermove", onPointerMove); + window.addEventListener("pointerup", onPointerUp); return () => { - window.removeEventListener("mousemove", onMouseMove); - window.removeEventListener("mouseup", onMouseUp); + window.removeEventListener("pointermove", onPointerMove); + window.removeEventListener("pointerup", onPointerUp); }; - }, [onMouseMove, onMouseUp]); + }, [onPointerMove, onPointerUp]); const resetView = useCallback(() => { setZoom(1); @@ -289,7 +291,8 @@ export function ImageDiffViewer({ beforeSrc, afterSrc, filename, mode }: ImageDi
{zoomControls} @@ -379,12 +384,12 @@ export function ImageDiffViewer({ beforeSrc, afterSrc, filename, mode }: ImageDi {/* Divider — always at sliderPct% of the container in screen space */}