Teal.fm frontend powered by slices.network tealfm-slices.wisp.place
tealfm slices
1import { useState } from "react"; 2 3interface AlbumArtProps { 4 releaseMbId: string | null | undefined; 5 alt: string; 6} 7 8export default function AlbumArt({ releaseMbId, alt }: AlbumArtProps) { 9 const [hasError, setHasError] = useState(false); 10 const [isLoading, setIsLoading] = useState(true); 11 12 if (!releaseMbId || hasError) { 13 return ( 14 <div className="w-10 h-10 bg-zinc-800 flex items-center justify-center"> 15 <svg className="w-5 h-5 text-zinc-600" fill="currentColor" viewBox="0 0 20 20"> 16 <path d="M18 3a1 1 0 00-1.196-.98l-10 2A1 1 0 006 5v9.114A4.369 4.369 0 005 14c-1.657 0-3 .895-3 2s1.343 2 3 2 3-.895 3-2V7.82l8-1.6v5.894A4.37 4.37 0 0015 12c-1.657 0-3 .895-3 2s1.343 2 3 2 3-.895 3-2V3z" /> 17 </svg> 18 </div> 19 ); 20 } 21 22 return ( 23 <> 24 {isLoading && <div className="w-10 h-10 bg-zinc-800 animate-pulse" />} 25 <img 26 src={`https://coverartarchive.org/release/${releaseMbId}/front-250`} 27 alt={alt} 28 className={`w-10 h-10 object-cover ${isLoading ? 'hidden' : ''}`} 29 onLoad={() => setIsLoading(false)} 30 onError={() => { 31 setIsLoading(false); 32 setHasError(true); 33 }} 34 /> 35 </> 36 ); 37}