feat(web): radial gradient + playlist title overlay + tile-size hierarchy
test-web / test (push) Failing after 33s
test-web / test (push) Failing after 33s
Second wave of Home visual polish (UI tasks 80/82/84): - Shell main background gets a 1200x600 radial gradient at the top using color-mix on fs-iron so the page reads with subtle depth instead of as a flat slab. - PlaylistCard moves the title onto the cover with a bottom-to-top gradient overlay. The server-generated 2x2 collage becomes mood texture; the Fraunces playlist name becomes the dominant element. Track count and refresh label stay below the art. Mirror albums shadow-sm/shadow-lg/ring-accent hover treatment on the art-wrap. - Tile-size hierarchy: Playlists w-52, Recently added w-44, Rediscover w-40. Visual weight tapers as you scroll down the page so the freshest content reads as most important.
This commit is contained in:
@@ -149,7 +149,11 @@
|
|||||||
href={`/playlists/${playlist.id}`}
|
href={`/playlists/${playlist.id}`}
|
||||||
class="group flex w-full flex-col items-start gap-2 rounded-md p-2 text-left hover:bg-surface-hover"
|
class="group flex w-full flex-col items-start gap-2 rounded-md p-2 text-left hover:bg-surface-hover"
|
||||||
>
|
>
|
||||||
<div class="art-wrap relative aspect-square w-full overflow-hidden rounded-md bg-surface-hover">
|
<div
|
||||||
|
class="art-wrap relative aspect-square w-full overflow-hidden rounded-md
|
||||||
|
bg-surface-hover shadow-sm transition-all duration-150
|
||||||
|
group-hover:shadow-lg group-hover:ring-1 group-hover:ring-accent/40"
|
||||||
|
>
|
||||||
{#if playlist.cover_url}
|
{#if playlist.cover_url}
|
||||||
<img
|
<img
|
||||||
src={playlist.cover_url}
|
src={playlist.cover_url}
|
||||||
@@ -161,6 +165,23 @@
|
|||||||
<span class="text-xs">No tracks yet</span>
|
<span class="text-xs">No tracks yet</span>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
<!-- Bottom-to-top gradient so the Fraunces title overlay below
|
||||||
|
is legible against any cover. The server's playlist cover
|
||||||
|
is often a 2x2 collage; the gradient mutes the collage so
|
||||||
|
the playlist NAME becomes the dominant element. -->
|
||||||
|
<div
|
||||||
|
class="pointer-events-none absolute inset-0 bg-gradient-to-t
|
||||||
|
from-black/85 via-black/40 to-transparent"
|
||||||
|
></div>
|
||||||
|
<!-- Title burned in at the bottom of the cover. Two lines max;
|
||||||
|
ellipsis. Fraunces (font-display) so it reads as
|
||||||
|
branded/curated content rather than just metadata. -->
|
||||||
|
<div class="pointer-events-none absolute inset-x-0 bottom-0 p-3">
|
||||||
|
<div
|
||||||
|
class="font-display text-base font-medium leading-tight text-text-primary
|
||||||
|
[display:-webkit-box] [-webkit-box-orient:vertical] [-webkit-line-clamp:2] overflow-hidden"
|
||||||
|
>{playlist.name}</div>
|
||||||
|
</div>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
aria-label={`Play ${playlist.name}`}
|
aria-label={`Play ${playlist.name}`}
|
||||||
@@ -172,7 +193,6 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full min-w-0">
|
<div class="w-full min-w-0">
|
||||||
<div class="truncate text-sm font-medium text-text-primary">{playlist.name}</div>
|
|
||||||
<div class="truncate text-xs text-text-muted">
|
<div class="truncate text-xs text-text-muted">
|
||||||
{playlist.track_count} {playlist.track_count === 1 ? 'track' : 'tracks'}
|
{playlist.track_count} {playlist.track_count === 1 ? 'track' : 'tracks'}
|
||||||
{#if !isOwn}
|
{#if !isOwn}
|
||||||
|
|||||||
@@ -135,7 +135,16 @@
|
|||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main class="overflow-y-auto p-4">
|
<!-- Subtle 1200x600 radial highlight at the top of the scroll
|
||||||
|
area fades the slate tone (fs-iron with alpha) into the
|
||||||
|
background. Adds depth so the page doesn't read as a flat
|
||||||
|
slab. color-mix lets the gradient theme-track in case the
|
||||||
|
palette token ever shifts. -->
|
||||||
|
<main
|
||||||
|
class="overflow-y-auto p-4"
|
||||||
|
style="background-image: radial-gradient(ellipse 1200px 600px at 50% -100px,
|
||||||
|
color-mix(in srgb, var(--fs-iron) 60%, transparent), transparent 70%);"
|
||||||
|
>
|
||||||
{@render children?.()}
|
{@render children?.()}
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
|
|||||||
@@ -142,7 +142,9 @@
|
|||||||
ariaLabel="Playlists"
|
ariaLabel="Playlists"
|
||||||
>
|
>
|
||||||
{#snippet item(rowItem: PlaylistRowItem)}
|
{#snippet item(rowItem: PlaylistRowItem)}
|
||||||
<div class="w-44">
|
<!-- Playlists at the page anchor: largest of the carousels.
|
||||||
|
Recently added stays at w-44; Rediscover steps down. -->
|
||||||
|
<div class="w-52">
|
||||||
{#if rowItem.kind === 'real'}
|
{#if rowItem.kind === 'real'}
|
||||||
<PlaylistCard playlist={rowItem.playlist} />
|
<PlaylistCard playlist={rowItem.playlist} />
|
||||||
{:else}
|
{:else}
|
||||||
@@ -195,7 +197,9 @@
|
|||||||
ariaLabel="Rediscover albums"
|
ariaLabel="Rediscover albums"
|
||||||
>
|
>
|
||||||
{#snippet item(album: import('$lib/api/types').AlbumRef)}
|
{#snippet item(album: import('$lib/api/types').AlbumRef)}
|
||||||
<div class="w-44"><AlbumCard {album} /></div>
|
<!-- Rediscover steps down vs Recently added to make the
|
||||||
|
tile-size hierarchy read top-to-bottom. -->
|
||||||
|
<div class="w-40"><AlbumCard {album} /></div>
|
||||||
{/snippet}
|
{/snippet}
|
||||||
</HorizontalScrollRow>
|
</HorizontalScrollRow>
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
Reference in New Issue
Block a user