import { useState } from 'react'; import { cn } from '@/lib/utils'; interface ImageWithFallbackProps extends React.ImgHTMLAttributes { /** * What to show when the image fails to load (or has no src). Defaults to a * subtle skate emoji on a muted background that fills the same box as the * image would have, so broken user-uploaded URLs never surface the browser's * ugly broken-image icon. */ fallback?: React.ReactNode; } /** * Drop-in replacement for that degrades gracefully when the source is * missing or 404s. Content images across the app (spots, events, marketplace * listings, crew logos, shop photos, tours, stash gear) come from * user-supplied URLs on arbitrary Blossom/host servers, which routinely go * away — without this they render a broken-image glyph. The fallback fills the * same layout box (className is applied to the wrapper) so nothing shifts. */ export function ImageWithFallback({ src, alt = '', className, fallback, ...props }: ImageWithFallbackProps) { const [failed, setFailed] = useState(false); if (!src || failed) { return (
{fallback ?? 🛹}
); } return ( {alt} setFailed(true)} {...props} /> ); } export default ImageWithFallback;