web-player: P3 — Artwork y Avatar unificados

Crea src/lib/components/ui/Artwork.svelte y Avatar.svelte (B.3) y
migra todos los usos de Cover, PlaylistArt, MixArt y ArtistAvatar
(Sidebar, Queue, TrackInfo, TrackContextMenu, AlbumContextMenu,
TrackTitleCell, AlbumCard, PlaylistCard, MixTile, AlbumHeader,
PlaylistHeader, Home, Explorar, mezcla, perfil de usuario, TopBar,
MobileHeader). Borra los 4 componentes viejos.

Artwork: tamaño decide dimensión y radio automáticamente (tokens
cover-*/radius de P1); cascada src → mosaico (≥4 trackIds) → primera
carátula → fallback, con caída en cascada si cada paso falla (antes
repartida en 3 componentes con lógica ligeramente distinta). Añade un
tamaño 'fill' (aspect-square w-full) no descrito en la spec, necesario
para las tarjetas de grid fluidas hasta que P9 introduzca MediaCard.

TrackTitleCell cambia su prop `coverSize` (clases Tailwind libres) por
`size: 'sm'|'lg'` delegando en Artwork. SearchResultRow pierde su prop
`kind` y el radio por tipo (ahora lo decide Artwork/Avatar).

Decisión de producto (P3, sin bloquear en pregunta): se quita el
nombre bajo el avatar de perfil en /u/[id] por ser redundante con el
título de CollectionHeader.

Small deltas de radio/tamaño documentados en README del plan (auto-
radio por tamaño reemplaza clases ad-hoc; ver tabla B.1.1/B.1.2).

Verificado con npm run check/build; sin QA visual autenticada (Docker
no disponible en esta sesión).
This commit is contained in:
2026-09-20 22:39:05 +02:00
parent 3e56725566
commit 521cafc5c4
25 changed files with 326 additions and 359 deletions
+7 -6
View File
@@ -4,7 +4,7 @@
import { liked } from '$lib/player/liked.svelte';
import { createPlaylistModal } from '$lib/playlists.svelte';
import type { SessionUser } from '$lib/types';
import PlaylistArt from './ui/PlaylistArt.svelte';
import Artwork from './ui/Artwork.svelte';
import Home from '@lucide/svelte/icons/house';
import Compass from '@lucide/svelte/icons/compass';
import ListMusic from '@lucide/svelte/icons/list-music';
@@ -97,12 +97,13 @@
? 'bg-surface-hover'
: 'hover:bg-hover'}"
>
<PlaylistArt
playlistId={playlist.id}
<Artwork
src="/api/playlists/{playlist.id}/cover?size=small&v={encodeURIComponent(
playlist.updatedAt
)}"
trackIds={playlist.coverTrackIds}
version={playlist.updatedAt}
size="small"
class="h-8.5 w-8.5 shrink-0 overflow-hidden rounded-lg opacity-90"
size="xs"
class="shrink-0 opacity-90"
/>
<div class="min-w-0 flex-1">
<div class="truncate text-sm {active ? 'text-fg' : 'text-fg-2'}">