From 829525506c5f2653749d111961925d4e5fda08b4 Mon Sep 17 00:00:00 2001 From: Jared Vititoe Date: Fri, 10 Jul 2026 17:57:33 -0400 Subject: [PATCH] fix(image-viewer): pan tracks the cursor 1:1 when zoomed The timeline image viewer's transform applied translate inside scale(), so dragging a zoomed image moved it by zoom x the cursor distance (panning outran the pointer). Divide the pan offset by zoom so it tracks 1:1 - matching the media-gallery lightbox fix. Co-Authored-By: Claude Opus 4.8 --- src/app/components/image-viewer/ImageViewer.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/app/components/image-viewer/ImageViewer.tsx b/src/app/components/image-viewer/ImageViewer.tsx index 39761e784..4429b0d40 100644 --- a/src/app/components/image-viewer/ImageViewer.tsx +++ b/src/app/components/image-viewer/ImageViewer.tsx @@ -86,7 +86,12 @@ export const ImageViewer = as<'div', ImageViewerProps>( className={css.ImageViewerImg} style={{ cursor, - transform: `scale(${zoom}) translate(${pan.translateX}px, ${pan.translateY}px)`, + // translate runs inside scale(), so divide by zoom to make a dragged + // pixel move the image one screen pixel (1:1 with the cursor) rather + // than `zoom` pixels. + transform: `scale(${zoom}) translate(${pan.translateX / zoom}px, ${ + pan.translateY / zoom + }px)`, }} src={src} alt={alt}