feat(web): CoverArt + reusable AlbumModal

CoverArt loads album art from the Cover Art Archive CDN by release-group MBID
(browser-side, cached, graceful placeholder fallback). AlbumModal shows cover +
tracklist (fetched from MB) with slots for a status chip and context actions.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jonathan
2026-07-12 15:14:34 +02:00
parent 3284059aba
commit 34235a2355
3 changed files with 150 additions and 0 deletions
+38
View File
@@ -0,0 +1,38 @@
"use client";
import { useState } from "react";
/** Album art from the Cover Art Archive (keyed by release-group MBID), loaded straight from
* their CDN by the browser — no backend, no MB API rate limit. Falls back to a placeholder
* when there's no MBID or no art. */
export function CoverArt({
rgMbid,
alt,
size = 250,
className,
}: {
rgMbid: string | null | undefined;
alt: string;
size?: 250 | 500;
className?: string;
}) {
const [failed, setFailed] = useState(false);
const cls = `cover ${className ?? ""}`.trim();
if (!rgMbid || failed) {
return (
<div className={`${cls} cover-fallback`} role="img" aria-label={alt}>
<span></span>
</div>
);
}
return (
// eslint-disable-next-line @next/next/no-img-element
<img
className={cls}
src={`https://coverartarchive.org/release-group/${rgMbid}/front-${size}`}
alt={alt}
loading="lazy"
onError={() => setFailed(true)}
/>
);
}