fix: carousel image lightbox
This commit is contained in:
@@ -41,6 +41,7 @@ import { postSourceHref, quoteCardBgStyle } from "./post-card-shared";
|
||||
import { PostActionsFooter } from "./post-actions-footer";
|
||||
import { PostCardMenu } from "./post-card-menu";
|
||||
import { PostImageLightbox } from "./post-image-lightbox";
|
||||
import { useTapGuard } from "./use-tap-guard";
|
||||
import { FeedFollowButton } from "./feed-follow-button";
|
||||
import { UpdateBackgroundModal } from "../update-background-modal";
|
||||
import { MentionsDrawer } from "../mentions-drawer";
|
||||
@@ -252,12 +253,9 @@ function ImageCarousel({
|
||||
}) {
|
||||
const [active, setActive] = useState(0);
|
||||
const scrollerRef = useRef<HTMLDivElement>(null);
|
||||
// Where the pointer went down, plus the scroller's position at that moment.
|
||||
// Swiping the carousel and tapping a photo have to stay independent: the
|
||||
// carousel scrolls natively (CSS scroll-snap), and browsers still fire a
|
||||
// click after some swipe gestures. Comparing both the pointer travel AND
|
||||
// whether the strip actually scrolled lets us drop those.
|
||||
const tapStart = useRef({ x: 0, y: 0, scrollLeft: 0 });
|
||||
// Swiping the carousel and tapping a photo have to stay independent — the
|
||||
// strip scrolls natively, and browsers still fire a click after some swipes.
|
||||
const { onPointerDown, wasTap } = useTapGuard(scrollerRef);
|
||||
|
||||
function onScroll(e: React.UIEvent<HTMLDivElement>) {
|
||||
const el = e.currentTarget;
|
||||
@@ -266,26 +264,6 @@ function ImageCarousel({
|
||||
setActive(Math.round(el.scrollLeft / w));
|
||||
}
|
||||
|
||||
function onPointerDown(e: React.PointerEvent) {
|
||||
tapStart.current = {
|
||||
x: e.clientX,
|
||||
y: e.clientY,
|
||||
scrollLeft: scrollerRef.current?.scrollLeft ?? 0,
|
||||
};
|
||||
}
|
||||
|
||||
/** True only for a genuine tap — barely any pointer travel and no scroll. */
|
||||
function wasTap(e: React.MouseEvent) {
|
||||
const moved =
|
||||
Math.abs(e.clientX - tapStart.current.x) > 8 ||
|
||||
Math.abs(e.clientY - tapStart.current.y) > 8;
|
||||
const scrolled =
|
||||
Math.abs(
|
||||
(scrollerRef.current?.scrollLeft ?? 0) - tapStart.current.scrollLeft,
|
||||
) > 4;
|
||||
return !moved && !scrolled;
|
||||
}
|
||||
|
||||
if (images.length === 1) {
|
||||
// Single image: no scroller, so every click is unambiguously a tap.
|
||||
return (
|
||||
@@ -293,7 +271,7 @@ function ImageCarousel({
|
||||
type="button"
|
||||
onClick={() => onOpen(0)}
|
||||
aria-label="View photo"
|
||||
className="relative block w-full aspect-square bg-muted cursor-zoom-in outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset"
|
||||
className="relative block w-full aspect-square bg-muted cursor-pointer outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset"
|
||||
>
|
||||
<Image
|
||||
src={images[0].url}
|
||||
@@ -328,7 +306,7 @@ function ImageCarousel({
|
||||
}}
|
||||
aria-roledescription="slide"
|
||||
aria-label={`View photo ${i + 1} of ${images.length}`}
|
||||
className="relative block w-full shrink-0 snap-start aspect-square bg-muted cursor-zoom-in outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset"
|
||||
className="relative block w-full shrink-0 snap-start aspect-square bg-muted cursor-pointer outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset"
|
||||
>
|
||||
<Image
|
||||
src={img.url}
|
||||
|
||||
Reference in New Issue
Block a user