web-player: P7 — filas (ListRow, MediaIdentity, EqBars)

Crea MediaIdentity.svelte (renombra y generaliza TrackTitleCell,
puramente presentacional: arte + título + subtítulo, sin manejo de
click) y ListRow.svelte encima (href|onclick, active, size xs/sm/lg,
variant row|card, leading/trailing/overlay). Usa MediaIdentity también
en player/TrackInfo... (pendiente: TrackInfo se deja para P12, que ya
tiene tarea explícita de tocar ese archivo).

Migra a ListRow: SearchResultRow (Explorar, 4 grupos — se borra el
componente), Inicio (Continuar escuchando, Populares, spotlight, Tus
playlists), Queue (A continuación), Sidebar (playlists). Las 6 tablas
de pista (AlbumTrackTable, PlaylistTrackTable, library, liked, mixes,
LibraryPicker) migran a MediaIdentity con su propio use:pressable
local, ya que TrackList (P8) todavía no existe.

EqBars gana prop `overlay` (fondo scrim/45, color on-art) que
sustituye a NowPlaying.svelte (borrado). Corrige de paso 6 llamadas a
plural() que P5 había dejado sin migrar (liked, library, mixes,
playlists, PlaylistHeader, Inicio).

Deltas documentados en el registro del plan: fila activa de Sidebar
ahora usa el tinte de acento (antes gris neutro); tarjeta "Tus
playlists" de Inicio pierde la línea de autor redundante y su radio
pasa a rounded-art; filas de Queue pierden el opacity-80 del arte.

Verificado con npm run check/build; sin QA visual autenticada (Docker
no disponible en esta sesión).
This commit is contained in:
2026-09-21 00:14:20 +02:00
parent 9fd0bf46d6
commit 137a3b62bb
19 changed files with 407 additions and 390 deletions
@@ -8,7 +8,8 @@
import TrackRow from '$lib/components/ui/TrackRow.svelte';
import TrackMeta from '$lib/components/ui/TrackMeta.svelte';
import TrackIndexCell from '$lib/components/ui/TrackIndexCell.svelte';
import TrackTitleCell from '$lib/components/ui/TrackTitleCell.svelte';
import MediaIdentity from '$lib/components/ui/MediaIdentity.svelte';
import { pressable } from '$lib/actions/pressable';
type AlbumTrack = ApiTrackLike & { duration: number | string; listensCount: number | string };
@@ -34,15 +35,23 @@
{@const active = player.current.id === track.id}
<TrackRow {active}>
<TrackIndexCell index={i} {active} playing={player.playing} onToggle={() => playFrom(i)} />
<TrackTitleCell
trackId={track.id}
title={track.title}
artist={track.artist}
ownerUserId={track.ownerUserId}
explicit={track.isExplicit}
{active}
onClick={() => playFrom(i)}
/>
<!-- svelte-ignore a11y_click_events_have_key_events -->
<div
role="button"
tabindex="0"
use:pressable={() => playFrom(i)}
onclick={(event) => event.stopPropagation()}
class="flex min-w-0 flex-1 text-left"
>
<MediaIdentity
trackId={track.id}
title={track.title}
artist={track.artist}
ownerUserId={track.ownerUserId}
explicit={track.isExplicit}
{active}
/>
</div>
<TrackMeta class="hidden sm:block">{Number(track.listensCount)}</TrackMeta>
<TrackMeta>{fmtTime(Number(track.duration))}</TrackMeta>
{#if isOwner}
@@ -8,8 +8,9 @@
import TrackTable from '$lib/components/ui/TrackTable.svelte';
import TrackRow from '$lib/components/ui/TrackRow.svelte';
import TrackMeta from '$lib/components/ui/TrackMeta.svelte';
import TrackTitleCell from '$lib/components/ui/TrackTitleCell.svelte';
import NowPlaying from '$lib/components/ui/NowPlaying.svelte';
import MediaIdentity from '$lib/components/ui/MediaIdentity.svelte';
import { pressable } from '$lib/actions/pressable';
import EqBars from '$lib/components/ui/EqBars.svelte';
type LibraryTrack = ApiTrackLike & { duration: number | string; listensCount: number | string };
@@ -30,21 +31,29 @@
{#each library as track, i (track.id)}
{@const active = player.current.id === track.id}
<TrackRow {active}>
<TrackTitleCell
trackId={track.id}
title={track.title}
artist={track.artist}
ownerUserId={track.ownerUserId}
explicit={track.isExplicit}
{active}
onClick={() => playFrom(i)}
<!-- svelte-ignore a11y_click_events_have_key_events -->
<div
role="button"
tabindex="0"
use:pressable={() => playFrom(i)}
onclick={(event) => event.stopPropagation()}
class="flex min-w-0 flex-1 text-left"
>
{#snippet overlay()}
{#if player.current.id === track.id}
<NowPlaying paused={!player.playing} />
{/if}
{/snippet}
</TrackTitleCell>
<MediaIdentity
trackId={track.id}
title={track.title}
artist={track.artist}
ownerUserId={track.ownerUserId}
explicit={track.isExplicit}
{active}
>
{#snippet overlay()}
{#if player.current.id === track.id}
<EqBars overlay paused={!player.playing} />
{/if}
{/snippet}
</MediaIdentity>
</div>
<TrackMeta class="hidden sm:block">{Number(track.listensCount)}</TrackMeta>
<TrackMeta>{fmtTime(Number(track.duration))}</TrackMeta>
<form