diff --git a/app/features/art/components/ArtGrid.tsx b/app/features/art/components/ArtGrid.tsx
index 5a23bb8d0..0a97ae812 100644
--- a/app/features/art/components/ArtGrid.tsx
+++ b/app/features/art/components/ArtGrid.tsx
@@ -84,7 +84,7 @@ export function ArtGrid({
}
function BigImageDialog({ close, art }: { close: () => void; art: ListedArt }) {
- const [imageSettled, setImageSettled] = React.useState(false);
+ const [imageSettled, imageRef] = useImageSettled();
const { formatter } = useDateTimeFormat({
year: "numeric",
month: "numeric",
@@ -102,8 +102,7 @@ function BigImageDialog({ close, art }: { close: () => void; art: ListedArt }) {
src={art.url}
loading="lazy"
className={styles.dialogImg}
- onLoad={() => setImageSettled(true)}
- onError={() => setImageSettled(true)}
+ ref={imageRef}
/>
{art.tags || art.linkedUsers ? (
setImageSettled(true)}
- onError={() => setImageSettled(true)}
+ ref={imageRef}
className={enablePreview ? styles.thumbnail : undefined}
data-testid="art-image"
/>
@@ -301,3 +299,33 @@ function ImagePreview({
);
}
+
+/**
+ * Whether the image has finished loading (or failed to), and the ref to give it.
+ *
+ * Native listeners rather than `onLoad`/`onError` because React drops those
+ * events when the image settles right after mounting, e.g. when it comes from
+ * the browser cache.
+ */
+function useImageSettled() {
+ const [imageSettled, setImageSettled] = React.useState(false);
+
+ const imageRef = (image: HTMLImageElement | null) => {
+ if (!image) return;
+ if (image.complete) {
+ setImageSettled(true);
+ return;
+ }
+
+ const settle = () => setImageSettled(true);
+ image.addEventListener("load", settle);
+ image.addEventListener("error", settle);
+
+ return () => {
+ image.removeEventListener("load", settle);
+ image.removeEventListener("error", settle);
+ };
+ };
+
+ return [imageSettled, imageRef] as const;
+}
diff --git a/changelog/2026-09-19-art-details-stay-hidden.md b/changelog/2026-09-19-art-details-stay-hidden.md
new file mode 100644
index 000000000..5496af0cd
--- /dev/null
+++ b/changelog/2026-09-19-art-details-stay-hidden.md
@@ -0,0 +1,5 @@
+---
+navItem: art
+type: bug
+---
+Fixed art details and buttons sometimes staying hidden after the image had loaded