diff --git a/.changeset/rich-needles-move.md b/.changeset/rich-needles-move.md new file mode 100644 index 000000000..ac674266c --- /dev/null +++ b/.changeset/rich-needles-move.md @@ -0,0 +1,5 @@ +--- +"@frames.js/render": patch +--- + +fix: image loading state diff --git a/packages/render/src/frame-ui.tsx b/packages/render/src/frame-ui.tsx index 7c3918ac7..181270899 100644 --- a/packages/render/src/frame-ui.tsx +++ b/packages/render/src/frame-ui.tsx @@ -1,5 +1,5 @@ import { FrameTheme, FrameState } from "./types.js"; -import React, { ImgHTMLAttributes } from "react"; +import React, { ImgHTMLAttributes, useEffect } from "react"; import { FrameButton } from "frames.js"; export const defaultTheme: Required = { @@ -26,6 +26,14 @@ export type FrameUIProps = { /** A UI component only, that should be easy for any app to integrate */ export function FrameUI({ frameState, theme, FrameImage }: FrameUIProps) { + const [isImageLoading, setIsImageLoading] = React.useState(true); + + const isLoading = !!frameState.isLoading || isImageLoading; + + useEffect(() => { + if (frameState.frame?.image) setIsImageLoading(true); + }, [frameState]); + const resolvedTheme = getThemeWithDefaults(theme ?? {}); if (!frameState.homeframeUrl) return
Missing frame url
; if (frameState.error) { @@ -47,7 +55,7 @@ export function FrameUI({ frameState, theme, FrameImage }: FrameUIProps) { alt="Frame image" width={"100%"} style={{ - filter: frameState.isLoading ? "blur(4px)" : undefined, + filter: isLoading ? "blur(4px)" : undefined, borderTopLeftRadius: `${resolvedTheme.buttonRadius}px`, borderTopRightRadius: `${resolvedTheme.buttonRadius}px`, border: `1px solid ${resolvedTheme.buttonBorderColor}`, @@ -58,6 +66,10 @@ export function FrameUI({ frameState, theme, FrameImage }: FrameUIProps) { ? "1/1" : "1.91/1", }} + onLoad={() => { + setIsImageLoading(false); + }} + onError={() => setIsImageLoading(false)} /> {frameState.frame.inputText && ( (