fix: refine gallery viewer interactions

This commit is contained in:
2026-09-09 23:33:29 +03:30
parent 14acfcef06
commit 204dac2096
2 changed files with 18 additions and 1 deletions

View File

@@ -381,7 +381,7 @@
display: block;
width: 100%;
height: 100%;
object-fit: cover;
object-fit: contain;
}
.viewerDialog {

View File

@@ -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}