feat: enhance discovery, vibe sessions, and library enrichment
This commit is contained in:
@@ -23,9 +23,10 @@ export function PlaybackBar({ queueOpen, lyricsOpen, onToggleQueue, onToggleLyri
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="glass h-20 border-t border-border/70 px-4 flex items-center gap-4 shrink-0 z-20">
|
||||
<div className="glass border-t border-border/70 px-3 py-2 shrink-0 z-20 sm:h-20 sm:px-4 sm:py-0">
|
||||
<div className="flex flex-wrap items-center gap-x-3 gap-y-1.5 sm:flex-nowrap sm:gap-4">
|
||||
{/* Track info */}
|
||||
<div className="flex items-center gap-3 w-64 min-w-0 shrink-0">
|
||||
<div className="flex min-w-0 flex-1 items-center gap-2.5 sm:w-64 sm:flex-none sm:gap-3">
|
||||
{currentTrack ? (
|
||||
<>
|
||||
{currentTrack.album_id ? (
|
||||
@@ -52,7 +53,7 @@ export function PlaybackBar({ queueOpen, lyricsOpen, onToggleQueue, onToggleLyri
|
||||
<button
|
||||
onClick={handleDislike}
|
||||
title="Dislike (sends to quarantine)"
|
||||
className="flex-none rounded-md p-1.5 text-muted hover:bg-surface1 hover:text-red-400 transition-colors"
|
||||
className="flex-none rounded-md p-2 text-muted hover:bg-surface1 hover:text-red-400 transition-colors"
|
||||
aria-label="Dislike — move to quarantine"
|
||||
>
|
||||
<ThumbsDown size={16} />
|
||||
@@ -64,17 +65,17 @@ export function PlaybackBar({ queueOpen, lyricsOpen, onToggleQueue, onToggleLyri
|
||||
</div>
|
||||
|
||||
{/* Controls + scrubber */}
|
||||
<div className="flex-1 flex flex-col items-center gap-1">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="order-3 flex basis-full flex-col items-center gap-1 sm:order-none sm:flex-1 sm:basis-auto">
|
||||
<div className="flex items-center gap-2 sm:gap-3">
|
||||
<button
|
||||
onClick={toggleShuffle}
|
||||
className={`p-1.5 rounded-md transition-colors ${shuffle ? 'text-accent' : 'text-muted hover:text-text'}`}
|
||||
className={`rounded-md p-2 transition-colors ${shuffle ? 'text-accent' : 'text-muted hover:text-text'}`}
|
||||
aria-label={shuffle ? 'Disable shuffle' : 'Enable shuffle'}
|
||||
title={shuffle ? 'Shuffle on' : 'Shuffle off'}
|
||||
>
|
||||
<Shuffle size={18} />
|
||||
</button>
|
||||
<button onClick={prev} className="text-muted hover:text-text" aria-label="Previous">
|
||||
<button onClick={prev} className="rounded-md p-2 text-muted hover:text-text hover:bg-surface0" aria-label="Previous">
|
||||
<SkipBack size={20} />
|
||||
</button>
|
||||
<button
|
||||
@@ -85,19 +86,19 @@ export function PlaybackBar({ queueOpen, lyricsOpen, onToggleQueue, onToggleLyri
|
||||
>
|
||||
{isPlaying ? <Pause size={18} fill="currentColor" /> : <Play size={18} fill="currentColor" />}
|
||||
</button>
|
||||
<button onClick={next} className="text-muted hover:text-text" aria-label="Next">
|
||||
<button onClick={next} className="rounded-md p-2 text-muted hover:text-text hover:bg-surface0" aria-label="Next">
|
||||
<SkipForward size={20} />
|
||||
</button>
|
||||
<button
|
||||
onClick={cycleRepeat}
|
||||
className={`p-1.5 rounded-md transition-colors ${repeat !== 'none' ? 'text-accent' : 'text-muted hover:text-text'}`}
|
||||
className={`rounded-md p-2 transition-colors ${repeat !== 'none' ? 'text-accent' : 'text-muted hover:text-text'}`}
|
||||
aria-label={`Repeat: ${repeat}`}
|
||||
title={repeat === 'none' ? 'Repeat off' : repeat === 'all' ? 'Repeat all' : 'Repeat one'}
|
||||
>
|
||||
{repeat === 'one' ? <Repeat1 size={18} /> : <Repeat size={18} />}
|
||||
</button>
|
||||
</div>
|
||||
<div className="flex w-full max-w-lg items-center gap-2">
|
||||
<div className="flex w-full max-w-lg items-center gap-1.5 sm:gap-2">
|
||||
<span className="text-xs text-muted w-9 text-right tabular-nums">{formatDuration(position)}</span>
|
||||
<input
|
||||
type="range" min={0} max={Math.max(duration, 0.1)} step={0.1}
|
||||
@@ -112,18 +113,18 @@ export function PlaybackBar({ queueOpen, lyricsOpen, onToggleQueue, onToggleLyri
|
||||
</div>
|
||||
|
||||
{/* Volume + panel toggle */}
|
||||
<div className="flex items-center gap-3 w-48 justify-end shrink-0">
|
||||
<Volume2 size={18} className="text-muted flex-none" />
|
||||
<div className="order-2 flex items-center gap-1 justify-end shrink-0 sm:order-none sm:w-48 sm:gap-3">
|
||||
<Volume2 size={18} className="hidden text-muted flex-none sm:block" />
|
||||
<input
|
||||
type="range" min={0} max={1} step={0.01} value={volume}
|
||||
onChange={(e) => setVolume(Number(e.target.value))}
|
||||
className="w-20 h-1 cursor-pointer"
|
||||
className="hidden w-20 h-1 cursor-pointer sm:block"
|
||||
aria-label="Volume"
|
||||
/>
|
||||
<button
|
||||
onClick={onToggleLyrics}
|
||||
disabled={!currentTrack}
|
||||
className={`p-2 rounded-md transition-colors disabled:opacity-30 ${lyricsOpen ? 'bg-accent/20 text-accent' : 'text-muted hover:text-text'}`}
|
||||
className={`rounded-md p-2 transition-colors disabled:opacity-30 ${lyricsOpen ? 'bg-accent/20 text-accent' : 'text-muted hover:text-text hover:bg-surface0'}`}
|
||||
aria-label="Toggle lyrics"
|
||||
title="Lyrics"
|
||||
>
|
||||
@@ -131,13 +132,14 @@ export function PlaybackBar({ queueOpen, lyricsOpen, onToggleQueue, onToggleLyri
|
||||
</button>
|
||||
<button
|
||||
onClick={onToggleQueue}
|
||||
className={`p-2 rounded-md transition-colors ${queueOpen ? 'bg-accent/20 text-accent' : 'text-muted hover:text-text'}`}
|
||||
className={`rounded-md p-2 transition-colors ${queueOpen ? 'bg-accent/20 text-accent' : 'text-muted hover:text-text hover:bg-surface0'}`}
|
||||
aria-label="Toggle queue panel"
|
||||
title="Up Next"
|
||||
>
|
||||
<ListMusic size={18} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user