de5320a7b4
Heart appears on every entity rendering surface. ArtistRow restructured to a <div> with the link as a positioned overlay so the heart button can nest without invalid <button>-in-<a> markup. Shell nav grows a 'Liked' entry pointing at /library/liked.
49 lines
1.5 KiB
Svelte
49 lines
1.5 KiB
Svelte
<script lang="ts">
|
|
import type { AlbumRef, AlbumDetail } from '$lib/api/types';
|
|
import { FALLBACK_COVER } from '$lib/media/covers';
|
|
import { api } from '$lib/api/client';
|
|
import { enqueueTracks } from '$lib/player/store.svelte';
|
|
import LikeButton from './LikeButton.svelte';
|
|
|
|
let { album }: { album: AlbumRef } = $props();
|
|
|
|
function onImgError(e: Event) {
|
|
(e.currentTarget as HTMLImageElement).src = FALLBACK_COVER;
|
|
}
|
|
|
|
async function onAddClick(e: MouseEvent) {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
const detail = await api.get<AlbumDetail>(`/api/albums/${album.id}`);
|
|
enqueueTracks(detail.tracks);
|
|
}
|
|
</script>
|
|
|
|
<div class="relative">
|
|
<a
|
|
href={`/albums/${album.id}`}
|
|
class="group block rounded focus-visible:ring-2 focus-visible:ring-accent"
|
|
>
|
|
<img
|
|
src={album.cover_url}
|
|
alt=""
|
|
class="aspect-square w-full rounded object-cover transition-transform group-hover:scale-[1.03]"
|
|
loading="lazy"
|
|
onerror={onImgError}
|
|
/>
|
|
<div class="mt-2 truncate text-sm font-medium">{album.title}</div>
|
|
{#if album.year}
|
|
<div class="text-xs text-text-secondary">{album.year}</div>
|
|
{/if}
|
|
</a>
|
|
<div class="absolute right-2 top-2 flex gap-1">
|
|
<LikeButton entityType="album" entityId={album.id} />
|
|
<button
|
|
type="button"
|
|
aria-label="Add to queue"
|
|
onclick={onAddClick}
|
|
class="rounded-full bg-surface/80 px-2 py-1 text-sm text-text-secondary hover:text-text-primary focus-visible:ring-2 focus-visible:ring-accent"
|
|
>+</button>
|
|
</div>
|
|
</div>
|