@@ -23,6 +23,7 @@ export function FaviconImage({
2323 fallbackIcon,
2424} : FaviconImageProps ) {
2525 const [ error , setError ] = useState ( false ) ;
26+ const [ loaded , setLoaded ] = useState ( false ) ;
2627
2728 const hostname = domain
2829 . replace ( hostnameRegex , "" )
@@ -40,34 +41,41 @@ export function FaviconImage({
4041 hostname . includes ( "localhost" ) ||
4142 hostname . includes ( "127.0.0.1" ) ;
4243
43- if ( invalid || error ) {
44- return (
45- < div
46- className = { `${ className } flex items-center justify-center rounded-sm` }
47- style = { { width : size , height : size } }
48- >
49- { fallbackIcon || (
50- < GlobeIcon
51- aria-label = { altText || "Website icon" }
52- className = "text-muted"
53- size = { size }
54- weight = "duotone"
55- />
56- ) }
57- </ div >
58- ) ;
59- }
44+ const showFallback = invalid || error || ! loaded ;
6045
6146 const isGitHub = hostname === "github.com" ;
6247
63- return (
64- < Image
65- alt = { altText || `${ domain } favicon` }
66- className = { `${ className } ${ isGitHub ? "dark:invert" : "" } ` }
67- height = { size }
68- onError = { ( ) => setError ( true ) }
69- src = { `https://icons.duckduckgo.com/ip3/${ hostname } .ico` }
70- width = { size }
48+ const fallbackContent = fallbackIcon || (
49+ < GlobeIcon
50+ aria-label = { altText || "Website icon" }
51+ className = "text-muted"
52+ size = { size }
53+ weight = "duotone"
7154 />
7255 ) ;
56+
57+ return (
58+ < div
59+ className = { `${ className } relative flex shrink-0 items-center justify-center rounded-sm` }
60+ style = { { width : size , height : size , minWidth : size , minHeight : size } }
61+ >
62+ { showFallback && (
63+ < div className = { `absolute inset-0 flex items-center justify-center ${ loaded ? "opacity-0" : "opacity-100" } transition-opacity` } >
64+ { fallbackContent }
65+ </ div >
66+ ) }
67+ { ! invalid && (
68+ < Image
69+ alt = { altText || `${ domain } favicon` }
70+ className = { `${ isGitHub ? "dark:invert" : "" } ${ loaded ? "opacity-100" : "opacity-0" } transition-opacity` }
71+ height = { size }
72+ onError = { ( ) => setError ( true ) }
73+ onLoad = { ( ) => setLoaded ( true ) }
74+ src = { `https://icons.duckduckgo.com/ip3/${ hostname } .ico` }
75+ style = { { width : size , height : size } }
76+ width = { size }
77+ />
78+ ) }
79+ </ div >
80+ ) ;
7381}
0 commit comments