ATlast — you'll never need to find your favorites on another platform again. Find your favs in the ATmosphere.
atproto
1import { useState } from "react"; 2import { Globe } from "lucide-react"; 3 4interface FaviconIconProps { 5 url: string; 6 alt: string; 7 className?: string; 8 useButtonStyling?: boolean; 9} 10 11export default function FaviconIcon({ 12 url, 13 alt, 14 className, 15 useButtonStyling = false, 16}: FaviconIconProps) { 17 const [error, setError] = useState(false); 18 const [loaded, setLoaded] = useState(false); 19 20 // Define the base classes (applied to the image itself) 21 const imageClasses = "w-full h-full object-contain"; 22 23 // Define the special button classes conditionally 24 const boundaryClasses = useButtonStyling 25 ? "bg-white p-1 rounded-full shadow-md flex items-center justify-center" 26 : ""; // No special styling by default 27 28 // Combine the passed-in class name (for size) with the conditional boundary classes 29 const finalWrapperClasses = `${className || "w-4 h-4"} ${boundaryClasses}`; 30 31 if (error) { 32 return ( 33 <div className={`${finalWrapperClasses}`}> 34 <Globe className={`${imageClasses} text-neutral-500`} /> 35 </div> 36 ); 37 } 38 39 return ( 40 // Use the final combined classes on the wrapper 41 <div className={finalWrapperClasses}> 42 {/* Placeholder while loading */} 43 {!loaded && ( 44 <Globe 45 className={`${imageClasses} text-neutral-400 dark:text-neutral-500`} 46 /> 47 )} 48 49 {/* The actual image */} 50 <img 51 src={url} 52 alt={`${alt} favicon`} 53 className={imageClasses} 54 style={{ display: loaded ? "block" : "none" }} 55 onLoad={() => { 56 setLoaded(true); 57 setError(false); 58 }} 59 onError={() => { 60 setError(true); 61 }} 62 /> 63 </div> 64 ); 65}