ATlast — you'll never need to find your favorites on another platform again. Find your favs in the ATmosphere.
atproto
17
fork

Configure Feed

Select the types of activity you want to include in your feed.

at 0e44908bfb09f54559dbc307dbdec87b46c48bcf 65 lines 1.7 kB view raw
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}