Card preview: clicking empty space beside the info tile closes it

This commit is contained in:
2026-10-25 14:23:48 -05:00
parent 226878fdd7
commit fae1aa2b05
2 changed files with 17 additions and 3 deletions

View File

@@ -1364,6 +1364,7 @@ function ClickPreviewModal({
const shownImage = showBack && hasBack ? card.back_image_uri : card.image_uri; const shownImage = showBack && hasBack ? card.back_image_uri : card.image_uri;
const backdropRef = useRef<HTMLDivElement>(null); const backdropRef = useRef<HTMLDivElement>(null);
const modalRef = useRef<HTMLDivElement>(null); const modalRef = useRef<HTMLDivElement>(null);
const facesRef = useRef<HTMLDivElement>(null);
const infoRef = useRef<HTMLDivElement>(null); const infoRef = useRef<HTMLDivElement>(null);
// Compact mode: when the full layout (art + info tile) would be taller than // Compact mode: when the full layout (art + info tile) would be taller than
// the viewport — i.e. on phones, where the tile wraps below the art — show // the viewport — i.e. on phones, where the tile wraps below the art — show
@@ -1441,9 +1442,15 @@ function ClickPreviewModal({
] ]
.filter(Boolean) .filter(Boolean)
.join(" ")} .join(" ")}
onClick={(e) => e.stopPropagation()} onClick={(e) => {
e.stopPropagation();
// The modal's box spans the tallest child, so beside a short info
// tile (or between side-by-side DFC faces) there's empty space that
// is still "off the card" — treat a click there like the backdrop.
if (e.target === e.currentTarget || e.target === facesRef.current) onClose();
}}
> >
<div className="preview-modal-faces"> <div className="preview-modal-faces" ref={facesRef}>
{/* Only the front face can be horizontal (Battles) — a transformed {/* Only the front face can be horizontal (Battles) — a transformed
Battle's back face is always a normal, correctly-oriented Battle's back face is always a normal, correctly-oriented
creature card, per `CardRef.horizontal`'s doc comment. */} creature card, per `CardRef.horizontal`'s doc comment. */}

View File

@@ -2100,7 +2100,10 @@ tbody tr:hover {
.preview-modal { .preview-modal {
position: relative; position: relative;
margin: auto; margin: auto;
cursor: default; /* Its empty space (e.g. below a short info tile) closes the modal like the
backdrop does — see ClickPreviewModal — so only the actual content gets
the default cursor. */
cursor: zoom-out;
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
align-items: flex-start; align-items: flex-start;
@@ -2111,6 +2114,10 @@ tbody tr:hover {
.preview-modal-faces { .preview-modal-faces {
position: relative; position: relative;
} }
.preview-modal > :not(.preview-modal-faces),
.preview-modal-faces > * {
cursor: default;
}
/* Sized explicitly (Scryfall "normal" images are 488x680) rather than from /* Sized explicitly (Scryfall "normal" images are 488x680) rather than from
the image's intrinsic size, so the box is already its final size before the the image's intrinsic size, so the box is already its final size before the
image loads — ClickPreviewModal measures the layout on mount to decide on image loads — ClickPreviewModal measures the layout on mount to decide on