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