123 lines
3.8 KiB
HTML
Executable File
123 lines
3.8 KiB
HTML
Executable File
{{/* Persistent Audio Player */}}
|
|
<div
|
|
x-data="playerUI()"
|
|
x-show="$store.audio.currentTrack"
|
|
x-cloak
|
|
class="audio-player p-4"
|
|
role="region"
|
|
aria-label="Audio player"
|
|
>
|
|
<div class="container-wide flex items-center gap-4">
|
|
{{/* Track Info */}}
|
|
<div class="flex items-center gap-3 min-w-0 flex-1">
|
|
{{/* Cover */}}
|
|
<div
|
|
class="w-12 h-12 bg-surface-2 rounded overflow-hidden flex-shrink-0"
|
|
x-show="$store.audio.currentTrack?.image"
|
|
>
|
|
<img
|
|
:src="$store.audio.currentTrack?.image"
|
|
:alt="$store.audio.currentTrack?.title"
|
|
class="w-full h-full object-cover"
|
|
>
|
|
</div>
|
|
|
|
{{/* Title */}}
|
|
<div class="min-w-0">
|
|
<p
|
|
class="text-sm font-medium truncate"
|
|
x-text="$store.audio.currentTrack?.title || 'No track'"
|
|
></p>
|
|
<p class="text-xs text-text-muted">Valknar</p>
|
|
</div>
|
|
</div>
|
|
|
|
{{/* Controls */}}
|
|
<div class="flex items-center gap-4">
|
|
{{/* Play/Pause */}}
|
|
<button
|
|
@click="togglePlay()"
|
|
class="w-10 h-10 flex items-center justify-center rounded-full bg-accent text-surface-0 hover:scale-105 transition-transform"
|
|
:aria-label="$store.audio.isPlaying ? 'Pause' : 'Play'"
|
|
>
|
|
<svg
|
|
x-show="!$store.audio.isPlaying"
|
|
class="w-5 h-5 ml-0.5"
|
|
fill="currentColor"
|
|
viewBox="0 0 24 24"
|
|
>
|
|
<path d="M8 5v14l11-7z"/>
|
|
</svg>
|
|
<svg
|
|
x-show="$store.audio.isPlaying"
|
|
x-cloak
|
|
class="w-5 h-5"
|
|
fill="currentColor"
|
|
viewBox="0 0 24 24"
|
|
>
|
|
<path d="M6 4h4v16H6V4zm8 0h4v16h-4V4z"/>
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
|
|
{{/* Progress */}}
|
|
<div class="flex-1 max-w-md hidden sm:flex items-center gap-3">
|
|
<span class="text-xs text-text-muted tabular-nums" x-text="formatTime($store.audio.progress)">0:00</span>
|
|
<input
|
|
type="range"
|
|
min="0"
|
|
:max="$store.audio.duration || 100"
|
|
:value="$store.audio.progress"
|
|
@input="seek($event.target.value)"
|
|
class="audio-player__progress flex-1"
|
|
aria-label="Seek"
|
|
>
|
|
<span class="text-xs text-text-muted tabular-nums" x-text="formatTime($store.audio.duration)">0:00</span>
|
|
</div>
|
|
|
|
{{/* Volume */}}
|
|
<div class="hidden md:flex items-center gap-2">
|
|
<button
|
|
@click="toggleMute()"
|
|
class="p-2 text-text-secondary hover:text-text-primary transition-colors"
|
|
:aria-label="$store.audio.volume === 0 ? 'Unmute' : 'Mute'"
|
|
>
|
|
<svg
|
|
x-show="$store.audio.volume > 0"
|
|
class="w-5 h-5"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
viewBox="0 0 24 24"
|
|
>
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.536 8.464a5 5 0 010 7.072M17.5 6.5a8 8 0 010 11M11 5L6 9H2v6h4l5 4V5z"/>
|
|
</svg>
|
|
<svg
|
|
x-show="$store.audio.volume === 0"
|
|
x-cloak
|
|
class="w-5 h-5"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
viewBox="0 0 24 24"
|
|
>
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5.586 15H4a1 1 0 01-1-1v-4a1 1 0 011-1h1.586l4.707-4.707C10.923 3.663 12 4.109 12 5v14c0 .891-1.077 1.337-1.707.707L5.586 15z"/>
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2"/>
|
|
</svg>
|
|
</button>
|
|
<input
|
|
type="range"
|
|
min="0"
|
|
max="1"
|
|
step="0.01"
|
|
:value="$store.audio.volume"
|
|
@input="setVolume($event.target.value)"
|
|
class="w-20 audio-player__progress"
|
|
aria-label="Volume"
|
|
>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<style>
|
|
[x-cloak] { display: none !important; }
|
|
</style>
|