diff --git a/.changeset/fix-media-picker-broken-image.md b/.changeset/fix-media-picker-broken-image.md new file mode 100644 index 000000000..a6f397dba --- /dev/null +++ b/.changeset/fix-media-picker-broken-image.md @@ -0,0 +1,5 @@ +--- +"@emdash-cms/admin": patch +--- + +Fixes broken image collapsing media picker container — adds `onError` handler and fallback placeholder so Change/Remove buttons remain accessible when referenced image is missing from storage diff --git a/packages/admin/src/components/BlockKitMediaPickerField.tsx b/packages/admin/src/components/BlockKitMediaPickerField.tsx index 8ee052389..febadc32c 100644 --- a/packages/admin/src/components/BlockKitMediaPickerField.tsx +++ b/packages/admin/src/components/BlockKitMediaPickerField.tsx @@ -1,6 +1,6 @@ import { Button } from "@cloudflare/kumo"; import { useLingui } from "@lingui/react/macro"; -import { Image as ImageIcon, X } from "@phosphor-icons/react"; +import { Image as ImageIcon, ImageBroken, X } from "@phosphor-icons/react"; import * as React from "react"; import type { MediaItem } from "../lib/api"; @@ -35,7 +35,12 @@ export function BlockKitMediaPickerField({ }: BlockKitMediaPickerFieldProps) { const { t } = useLingui(); const [pickerOpen, setPickerOpen] = React.useState(false); + const [imageBroken, setImageBroken] = React.useState(false); const url = typeof value === "string" && value.length > 0 ? value : ""; + + React.useEffect(() => { + setImageBroken(false); + }, [url]); const filter = mimeTypeFilter ?? "image/"; const canPreview = isSafePreviewUrl(url); @@ -55,30 +60,65 @@ export function BlockKitMediaPickerField({
{canPreview ? ( -
- -
- - + imageBroken ? ( +
+
+ + {t`Image not found`} +
+
+ + +
+
+ ) : ( +
+ setImageBroken(true)} + /> +
+ + +
-
+ ) ) : ( - + imageBroken ? ( +
+
+ + {t`Image not found`} +
+
+ + +
-
+ ) : ( +
+ setImageBroken(true)} + /> +
+ + +
+
+ ) ) : (