music-web/web/src/components/navigation/NowPlayingMiniBar.tsx
Jarian Cottingham bc40a19c49 Initial commit: web frontend
React web app for the self-hosted music streaming project,
carved out from the music-app monorepo. Uses @music-app/shared
for shared types and utilities.
2026-08-21 18:44:05 +00:00

68 lines
2.8 KiB
TypeScript

import { Link } from 'react-router-dom'
import { motion } from 'framer-motion'
import { usePlayerStore } from '../../store/playerStore'
export function NowPlayingMiniBar() {
const currentSong = usePlayerStore(s => s.currentSong)
const isPlaying = usePlayerStore(s => s.isPlaying)
const togglePlay = usePlayerStore(s => s.togglePlay)
const next = usePlayerStore(s => s.next)
const previous = usePlayerStore(s => s.previous)
const progress = usePlayerStore(s => s.progress)
const progressPercent = currentSong ? (progress / currentSong.duration) * 100 : 0
return (
<motion.div
className="fixed bottom-12 left-0 right-0 z-40"
initial={{ y: 100 }}
animate={{ y: 0 }}
exit={{ y: 100 }}
transition={{ type: 'spring', duration: 0.5, bounce: 0.3 }}
>
<div className="h-0.5 bg-music-border relative overflow-hidden">
<motion.div
className="h-full bg-music-accent"
style={{ width: `${progressPercent}%` }}
transition={{ duration: 0.5 }}
/>
<div
className="absolute top-0 h-full bg-music-accent/30 blur-sm"
style={{ width: `${progressPercent}%` }}
/>
</div>
<div className="bg-music-card/95 backdrop-blur-lg border-t border-music-border">
<Link to="/now-playing" className="flex items-center gap-3 px-4 py-2 max-w-6xl mx-auto">
<motion.div
className="w-10 h-10 rounded-full vinyl-record flex-shrink-0"
animate={isPlaying ? { rotate: 360 } : { rotate: 0 }}
transition={isPlaying ? { duration: 3, repeat: Infinity, ease: 'linear' } : {}}
/>
<div className="min-w-0 flex-1">
<motion.p
className="text-sm font-medium truncate"
key={currentSong?.id}
initial={{ opacity: 0, x: -10 }}
animate={{ opacity: 1, x: 0 }}
>
{currentSong?.title || 'No song'}
</motion.p>
<p className="text-xs text-music-muted truncate">{currentSong?.artist}</p>
</div>
<div className="flex items-center gap-2 flex-shrink-0">
<button onClick={previous} className="material-icons text-music-text hover:text-music-accent transition-colors">skip_previous</button>
<motion.button
onClick={togglePlay}
whileHover={{ scale: 1.1 }}
whileTap={{ scale: 0.9 }}
className="material-icons text-xl text-music-accent"
>
{isPlaying ? 'pause_circle' : 'play_circle'}
</motion.button>
<button onClick={next} className="material-icons text-music-text hover:text-music-accent transition-colors">skip_next</button>
</div>
</Link>
</div>
</motion.div>
)
}