Unify web-player design tokens and componentize collection headers

Migrates remaining one-off colors (bg-white/[N%], border-white/N, hardcoded
shadows/gradients) to the existing --mf-* tokens so light mode reacts
consistently everywhere, including a fix to --color-hover which was
hardcoded instead of pointing at --mf-surface-2. Extracts CollectionHeader
(album/playlist/mix/liked headers) and AccountMenu (TopBar/MobileHeader)
to remove five and two duplicated implementations respectively, and
normalizes inconsistent empty-state copy.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-15 17:53:47 +02:00
co-authored by Claude Sonnet 5
parent 33a9e886be
commit c947cdac1c
40 changed files with 463 additions and 448 deletions
@@ -10,6 +10,7 @@
import Button from '$lib/components/ui/Button.svelte';
import Alert from '$lib/components/ui/Alert.svelte';
import MixArt from '$lib/components/ui/MixArt.svelte';
import CollectionHeader from '$lib/components/ui/CollectionHeader.svelte';
import TrackTable from '$lib/components/ui/TrackTable.svelte';
import TrackRow from '$lib/components/ui/TrackRow.svelte';
import TrackMeta from '$lib/components/ui/TrackMeta.svelte';
@@ -67,43 +68,31 @@
<Page>
<BackLink href="/" label="Volver al inicio" />
<div class="mt-3 flex flex-col gap-5 sm:mt-4 sm:flex-row sm:items-end sm:gap-6">
<MixArt
{items}
class="h-36 w-36 shrink-0 rounded-[18px] shadow-[0_24px_56px_rgba(0,0,0,.55)] sm:h-41 sm:w-41"
/>
<div class="min-w-0 flex-1">
<p class="text-[10.5px] font-semibold tracking-[0.16em] text-fg-2 uppercase">Mezcla</p>
<h1
class="mt-1.5 font-display text-[28px] font-semibold tracking-[-0.035em] break-words text-fg sm:text-[33px]"
>
{mix.title}
</h1>
{#if mix.subtitle}
<p class="mt-3 text-base text-fg-2">{mix.subtitle}</p>
{/if}
<p class="mt-1 text-sm text-muted">
{items.length}
{items.length === 1 ? 'canción' : 'canciones'} · {fmtTime(totalSeconds)}
</p>
</div>
</div>
<div class="mt-6 flex flex-wrap items-center gap-2.5 sm:mt-7">
<Button size="sm" onclick={playAll} disabled={queue.length === 0}>
{#if isCurrentQueue && player.playing}
<Pause class="h-4 w-4" strokeWidth={1.5} />
Pausar
{:else}
<Play class="h-4 w-4" strokeWidth={1.5} />
Reproducir
{/if}
</Button>
<Button variant="secondary" size="sm" onclick={playShuffled} disabled={queue.length === 0}>
<Shuffle class="h-4 w-4" />
Aleatorio
</Button>
</div>
<CollectionHeader
eyebrow="Mezcla"
title={mix.title}
description={mix.subtitle ?? undefined}
meta="{items.length} {items.length === 1 ? 'canción' : 'canciones'} · {fmtTime(totalSeconds)}"
>
{#snippet cover()}
<MixArt {items} class="h-36 w-36 shrink-0 rounded-[18px] shadow-cover-lg sm:h-41 sm:w-41" />
{/snippet}
{#snippet actions()}
<Button size="sm" onclick={playAll} disabled={queue.length === 0}>
{#if isCurrentQueue && player.playing}
<Pause class="h-4 w-4" strokeWidth={1.5} />
Pausar
{:else}
<Play class="h-4 w-4" strokeWidth={1.5} />
Reproducir
{/if}
</Button>
<Button variant="secondary" size="sm" onclick={playShuffled} disabled={queue.length === 0}>
<Shuffle class="h-4 w-4" />
Aleatorio
</Button>
{/snippet}
</CollectionHeader>
{#if form?.message}
<Alert tone="danger" class="mt-4">{form.message}</Alert>