web-player: rows (ListRow, MediaIdentity, EqBars)

Add MediaIdentity.svelte (renames and generalizes TrackTitleCell,
purely presentational: art + title + subtitle, no click handling)
and ListRow.svelte on top of it (href|onclick, active, size xs/sm/lg,
variant row|card, leading/trailing/overlay). Also used by
player/TrackInfo... (TrackInfo itself is left for a later pass, which
already has an explicit task to touch that file).

Migrated to ListRow: SearchResultRow (Explore, 4 groups — component
removed), Home (Continue listening, Popular, spotlight, Your
playlists), Queue (Up next), Sidebar (playlists). The 6 track tables
(AlbumTrackTable, PlaylistTrackTable, library, liked, mixes,
LibraryPicker) migrate to MediaIdentity with their own local
use:pressable, since TrackList doesn't exist yet.

EqBars gains an `overlay` prop (scrim/45 background, on-art color)
replacing NowPlaying.svelte (removed). Along the way, fixes 6
plural() calls that a previous pass had left unmigrated (liked,
library, mixes, playlists, PlaylistHeader, Home).

Deltas documented in the plan's log: Sidebar's active row now uses
the accent tint (previously neutral gray); Home's "Your playlists"
card loses its redundant author line and its radius becomes
rounded-art; Queue rows lose the art's opacity-80.

Verified with npm run check/build; no authenticated visual QA (Docker
unavailable this session).
This commit is contained in:
2026-09-21 00:14:20 +02:00
parent 14ee1dc45d
commit fb4a8ccc0e
19 changed files with 407 additions and 390 deletions
@@ -21,7 +21,7 @@
import { enhance } from '$app/forms';
import type { LucideIcon } from '@lucide/svelte';
import ChevronRight from '@lucide/svelte/icons/chevron-right';
import Artwork from './Artwork.svelte';
import MediaIdentity from './MediaIdentity.svelte';
import GlassMenu from './GlassMenu.svelte';
import MenuItem from './MenuItem.svelte';
@@ -93,14 +93,14 @@
{/each}
<button
type="submit"
class="flex w-full items-center gap-3 rounded-control px-2 py-2.5 text-left text-sm font-medium text-fg transition hover:bg-hover"
class="flex w-full items-center rounded-control px-2 py-2.5 text-left text-sm font-medium text-fg transition hover:bg-hover"
>
<Artwork
src="/api/playlists/{playlist.id}/cover?size=small"
<MediaIdentity
title={playlist.name}
coverSrc="/api/playlists/{playlist.id}/cover?size=small"
size="xs"
class="shrink-0"
titleClass="text-fg-2"
/>
<span class="truncate text-fg-2">{playlist.name}</span>
</button>
</form>
{/each}