Gallery View Zooming and Panning Feature#1596
Conversation
JasonWildMe
left a comment
There was a problem hiding this comment.
Hey @Joey-Li0118
Thanks for looking at this issue! To keep responses faster for open source commits, we are leveraging Claude+Codex for code reviews. Overall, the response was positive (Thank you!). They flagged a few issues to address first if you have time.
Scope: single file, frontend/src/pages/SearchPages/searchResultTabs/ImageGalleryModal.jsx (+84/−3). Adds zoom/pan to
the Gallery-View image modal, fixing #1569. The author copied the zoom/pan logic from the working
components/ImageModal.jsx.
Verdict: The feature works for the plain-image case and the port is faithful. But there's one real correctness bug
that defeats the existing annotation-overlay feature in this same modal, plus a UX gap around drag. Both are worth
fixing before merge.
🔴 HIGH — Annotation overlay boxes drift out of alignment when zoomed/panned
ImageGalleryModal.jsx applies the transform: translate(...) scale(...) directly to the (the new style block at
the img), but the annotation rectangles (imageStore.showAnnotations && rects.length > 0 && rects.map(...)) are
siblings of the img inside the same position-relative wrapper — they are not transformed.
Result: with "Show Annotations" on, zooming/panning moves and scales the image while the red boxes stay pinned to the
original (unzoomed) coordinate space, so they no longer line up with the features they mark.
The reference ImageModal.jsx deliberately avoids this: it puts the transform on a wrapper div (#image-modal-image-box)
that contains both the and the rects, so they zoom/pan together. The fix is to mirror that structure — move the
transform/cursor onto a wrapper enclosing the image and the rects map, rather than onto the itself.
🟡 MEDIUM — Native image-drag not suppressed, interferes with panning
The PR's gets onMouseDown={onMouseDown} but is missing draggable={false} and onDragStart={(e) =>
e.preventDefault()}. The reference image has both. Without them, starting a pan on a zoomed image can trigger the
browser's native image-drag (ghost image / drop cursor), fighting the pan gesture. Add both props to the .
🟢 LOW — Zoom buttons: hardcoded English + missing aria-label
The two new buttons use title="Zoom In" / title="Reset Zoom" with no aria-label, while the neighboring Download/Close
buttons have aria-labels. Wildbook's contribution guide requires UI copy localized to 5 languages. Note this matches
the reference ImageModal.jsx, which also hardcodes these — so it's a pre-existing pattern, not a new regression.
Ideally localize via react-intl and add aria-labels (and fix the reference too in a follow-up).
🟢 LOW — "Reset Zoom" with a zoom-out icon, no incremental zoom-out
The second button resets to zoom = 1 (not a step-down) but shows the bi-zoom-out icon. Functionally identical to the
reference, so acceptable, but a user expecting incremental zoom-out won't get it. Worth a UX confirmation.
⚪ NIT — No-op styles copied onto the
position: "relative" and overflow: "hidden" were copied onto the style; overflow has no effect on a replaced
element like , and clipping should live on the container. These become moot once the transform moves to the
wrapper (HIGH fix).
⚪ NIT — Pre-existing dead thumbsRef effect
The thumbsRef effect (if (!s || s.destroyed) return; ...) never runs in this component because no element is assigned
to thumbsRef (the gallery modal has no Swiper thumbnails), so its scale recalculation is dead and the real
scaleX/scaleY comes from the img onLoad. It also reads imgRef.current.clientWidth without a null guard. This is
pre-existing (not introduced by this PR), but since the PR is already touching scale state, it'd be a good moment to
delete it.
ImageGalleryModal.jsx was edited to feature some of the same code as ImageModal.jsx which allows for the panning and zooming of images in the Gallery View page.
PR fixes #1569