feat(web): add CompactTrackCard for Most played rows

Small 140px clickable card showing album cover, title, and artist name.
Clicking calls playQueue(sectionTracks, index) to play through the full
section list. Includes Vitest tests for click and render behaviour.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-01 20:19:16 -04:00
parent c7e7dd269b
commit 0586483a42
2 changed files with 86 additions and 0 deletions
@@ -0,0 +1,44 @@
<script lang="ts">
import type { TrackRef } from '$lib/api/types';
import { playQueue } from '$lib/player/store.svelte';
import { FALLBACK_COVER } from '$lib/media/covers';
let {
track,
sectionTracks,
index
}: {
track: TrackRef;
sectionTracks: TrackRef[];
index: number;
} = $props();
const coverUrl = $derived(`/api/albums/${track.album_id}/cover`);
function onImgError(e: Event) {
(e.currentTarget as HTMLImageElement).src = FALLBACK_COVER;
}
function onClick() {
playQueue(sectionTracks, index);
}
</script>
<button
type="button"
aria-label={`Play ${track.title}`}
onclick={onClick}
class="card group block w-36 rounded text-left focus-visible:ring-2 focus-visible:ring-accent"
>
<div class="aspect-square w-full overflow-hidden rounded-md bg-surface-hover">
<img
src={coverUrl}
alt=""
class="h-full w-full object-cover transition-transform group-hover:scale-[1.03]"
loading="lazy"
onerror={onImgError}
/>
</div>
<div class="mt-2 truncate text-xs font-medium text-text-primary">{track.title}</div>
<div class="truncate text-xs text-text-secondary">{track.artist_name}</div>
</button>