fix: refine gallery viewer interactions
This commit is contained in:
@@ -381,7 +381,7 @@
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.viewerDialog {
|
||||
|
||||
@@ -33,7 +33,9 @@ export function CaseStudyGallery({
|
||||
const closeRef = useRef<HTMLButtonElement>(null);
|
||||
const stageRef = useRef<HTMLButtonElement>(null);
|
||||
const thumbnailRefs = useRef<Array<HTMLButtonElement | null>>([]);
|
||||
const viewerThumbnailRefs = useRef<Array<HTMLButtonElement | null>>([]);
|
||||
const swipeStart = useRef<{ pointerId: number; x: number; y: number } | null>(null);
|
||||
const suppressCanvasClick = useRef(false);
|
||||
const selected = items[selectedIndex];
|
||||
|
||||
const selectImage = useCallback((index: number) => {
|
||||
@@ -44,6 +46,11 @@ export function CaseStudyGallery({
|
||||
block: 'nearest',
|
||||
inline: 'nearest',
|
||||
});
|
||||
viewerThumbnailRefs.current[normalizedIndex]?.scrollIntoView({
|
||||
behavior: window.matchMedia('(prefers-reduced-motion: reduce)').matches ? 'auto' : 'smooth',
|
||||
block: 'nearest',
|
||||
inline: 'nearest',
|
||||
});
|
||||
}, [items.length]);
|
||||
|
||||
const showPrevious = useCallback(() => selectImage(selectedIndex - 1), [selectImage, selectedIndex]);
|
||||
@@ -108,6 +115,10 @@ export function CaseStudyGallery({
|
||||
swipeStart.current = null;
|
||||
const deltaX = event.clientX - start.x;
|
||||
const deltaY = event.clientY - start.y;
|
||||
if (Math.abs(deltaX) > 8 || Math.abs(deltaY) > 8) {
|
||||
suppressCanvasClick.current = true;
|
||||
window.setTimeout(() => { suppressCanvasClick.current = false; }, 0);
|
||||
}
|
||||
if (Math.abs(deltaX) < 48 || Math.abs(deltaX) <= Math.abs(deltaY)) return;
|
||||
|
||||
const advance = isRtl ? deltaX > 0 : deltaX < 0;
|
||||
@@ -143,6 +154,7 @@ export function CaseStudyGallery({
|
||||
sizes="(max-width: 650px) calc(100vw - 2rem), (max-width: 1100px) calc(100vw - 4rem), 68rem"
|
||||
className={styles.galleryStageImage}
|
||||
unoptimized
|
||||
loading="eager"
|
||||
onLoad={preloadAdjacentImages}
|
||||
/>
|
||||
<span className={styles.expandBadge} aria-hidden="true"><Expand size={18} /></span>
|
||||
@@ -227,6 +239,10 @@ export function CaseStudyGallery({
|
||||
onPointerDown={handleSwipeStart}
|
||||
onPointerUp={handleSwipeEnd}
|
||||
onPointerCancel={() => { swipeStart.current = null; }}
|
||||
onClick={(event) => {
|
||||
if (suppressCanvasClick.current) return;
|
||||
if (event.target === event.currentTarget) closeViewer();
|
||||
}}
|
||||
>
|
||||
<Image
|
||||
key={`viewer-${selected.image.src}`}
|
||||
@@ -255,6 +271,7 @@ export function CaseStudyGallery({
|
||||
{items.map((item, index) => (
|
||||
<button
|
||||
key={`viewer-thumbnail-${item.image.src}`}
|
||||
ref={(node) => { viewerThumbnailRefs.current[index] = node; }}
|
||||
type="button"
|
||||
className={styles.viewerThumbnail}
|
||||
data-selected={index === selectedIndex}
|
||||
|
||||
Reference in New Issue
Block a user