player layout shenanigans

This commit is contained in:
2026-02-06 04:04:10 -08:00
parent 3418d19a57
commit 291b8d5d21
2 changed files with 398 additions and 408 deletions

View File

@@ -453,11 +453,11 @@
{/if}
</svelte:head>
{#if isMobile}
<!-- Mobile: mini bar + expandable drawer -->
<div
class="fixed bottom-0 left-0 right-0 z-50 border-t bg-background/95 backdrop-blur shadow-2xl"
>
<!-- Mobile UI is allowed to render as an overlay even if this component is mounted
inside the desktop sidebar column. We hide it on lg+ via CSS, not by unmounting. -->
<div
class="lg:hidden fixed bottom-0 left-0 right-0 z-50 border-t bg-background/95 backdrop-blur shadow-2xl"
>
<div class="mx-auto flex max-w-4xl items-center gap-2 px-3 py-2">
<button
class="inline-flex h-8 w-8 items-center justify-center rounded border"
@@ -623,9 +623,7 @@
step="0.01"
value={snap.volume}
oninput={(e) =>
setVolume(
Number((e.currentTarget as HTMLInputElement).value),
)}
setVolume(Number((e.currentTarget as HTMLInputElement).value))}
/>
</label>
</div>
@@ -695,12 +693,11 @@
</div>
</div>
{/if}
</div>
{:else}
<!-- Desktop: sticky, in-flow sidebar (sticks vertically, flows horizontally in the layout column) -->
<aside
class="sticky top-4 h-[calc(100dvh-2rem)] overflow-hidden bg-background flex flex-col"
>
</div>
<!-- Desktop UI stays in-flow in the right grid column. Hide on small screens via CSS. -->
<aside
class="hidden lg:flex sticky top-4 h-[calc(100dvh-2rem)] overflow-hidden bg-background flex-col"
>
<div class="flex items-center gap-2 border-b px-3 py-3">
<div class="min-w-0 flex-1">
<div class="truncate text-sm font-semibold">Player</div>
@@ -853,9 +850,7 @@
step="0.01"
value={snap.volume}
oninput={(e) =>
setVolume(
Number((e.currentTarget as HTMLInputElement).value),
)}
setVolume(Number((e.currentTarget as HTMLInputElement).value))}
/>
</label>
</div>
@@ -886,9 +881,7 @@
<span class="text-muted-foreground"></span>
{/if}
<div class="min-w-0 flex-1">
<div
class="flex flex-wrap items-baseline gap-x-2 gap-y-1"
>
<div class="flex flex-wrap items-baseline gap-x-2 gap-y-1">
{#if typeNumberLabel(item.track)}
<span
class="rounded bg-muted px-2 py-0.5 text-sm text-muted-foreground"
@@ -904,8 +897,7 @@
<div class="mt-1 text-foreground/80">
{(item.track.title ?? "").trim() || "Unknown title"}
<span class="text-sm text-muted-foreground">
{(item.track.artist ?? "").trim() ||
"Unknown Artist"}
{(item.track.artist ?? "").trim() || "Unknown Artist"}
</span>
</div>
</div>
@@ -927,10 +919,8 @@
</div>
</div>
{/if}
</aside>
{/if}
</aside>
<!-- Single global audio element (hidden but functional) -->
<audio
bind:this={audioEl}
class="hidden"

View File

@@ -21,15 +21,15 @@
{@render children()}
</main>
<!-- Desktop sidebar column (in normal flow).
Reserve space in the grid, but render the player only once below. -->
<aside class="hidden lg:block"></aside>
</div>
<!-- Single GlobalPlayer instance (client-only).
It renders either the desktop sidebar UI or the mobile bar/drawer internally. -->
<ClientOnly showFallback={false}>
<!-- Desktop sidebar column (in normal flow) -->
<aside class="hidden lg:block">
<ClientOnly showFallback={false}>
{#snippet children()}
<GlobalPlayer />
{/snippet}
</ClientOnly>
</ClientOnly>
</aside>
</div>
<!-- Mobile player is rendered by the same GlobalPlayer instance above.
On small screens, it uses fixed positioning internally so it can overlay. -->