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).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-20 22:39:05 +02:00
co-authored by Claude Sonnet 5
parent d447495933
commit 1186903d22
25 changed files with 326 additions and 359 deletions
@@ -1,6 +1,6 @@
<script lang="ts">
import type { Snippet } from 'svelte';
import Cover from './Cover.svelte';
import Artwork from './Artwork.svelte';
import ExplicitBadge from './ExplicitBadge.svelte';
import ArtistLink from './ArtistLink.svelte';
@@ -10,7 +10,7 @@
artist?: string | null;
ownerUserId?: string | number | null;
coverSrc?: string | null;
coverSize?: string;
size?: 'sm' | 'lg';
explicit?: boolean;
active?: boolean;
titleClass?: string;
@@ -25,7 +25,7 @@
artist,
ownerUserId,
coverSrc,
coverSize = 'h-10.5 w-10.5',
size = 'sm',
explicit = false,
active = false,
titleClass = '',
@@ -53,15 +53,9 @@
onkeydown={onKeydown}
class="flex min-w-0 items-center gap-3.5 text-left"
>
<Cover
{trackId}
src={coverSrc}
size="small"
alt={title}
class="{coverSize} shrink-0 rounded-control"
>
<Artwork trackIds={[trackId]} src={coverSrc} {size} alt={title} class="shrink-0">
{@render overlay?.()}
</Cover>
</Artwork>
<div class="min-w-0">
<div class="flex min-w-0 items-center gap-2">
{#if explicit}