Docs
Go back
Component by
OV
OblivionSoldiers Rage
Tha Mechanic
1:313:46
TSX
sonic-pulse-card
"use client"
import React, { useState } from "react"
import { motion, AnimatePresence } from "framer-motion"
import {
Play,
Pause,
SkipBack,
SkipForward,
Volume2,
Heart,
Music2,
MoreHorizontal
} from "lucide-react"
import { cn } from "@/lib/utils"
export const componentMeta = {
name: "Sonic Pulse Player",
description: "A premium glassmorphic media player with dynamic frequency visualizers and smooth animations.",
props: {
title: { type: "string", description: "Track title", default: '"Soldiers Rage"' },
artist: { type: "string", description: "Artist name", default: '"Tha Mechanic"' },
coverUrl: { type: "string", description: "URL for the album art", default: '""' },
accentColor: { type: "string", description: "Primary accent color", default: '"#6366f1"' }
}
}
export default function SonicPulseCard({
title = "Soldiers Rage",
artist = "Tha Mechanic",
coverUrl,
accentColor = "#6366f1", // Indigo-500
}: {
title?: string
artist?: string
coverUrl?: string
accentColor?: string
}) {
const [isPlaying, setIsPlaying] = useState(false)
const [progress, setProgress] = useState(42) // Percentage
const [isLiked, setIsLiked] = useState(false)
// Frequency bar animation variants
const barVariants: any = {
playing: (i: number) => ({
scaleY: [0.3, 1, 0.4, 0.8, 0.3],
transition: {
repeat: Infinity,
duration: 0.8,
delay: i * 0.15,
ease: "easeInOut",
},
}),
paused: {
scaleY: 0.1,
transition: { duration: 0.5, ease: "easeOut" }
}
}
return (
<div className="group relative w-full max-w-[320px] overflow-hidden rounded-2xl border border-white/10 bg-zinc-900/40 backdrop-blur-xl transition-all duration-500 hover:border-white/20 hover:shadow-[0_0_30px_rgba(0,0,0,0.5)]">
{/* Progress Glow Effect */}
<div
className="absolute inset-0 opacity-20 transition-opacity duration-1000 group-hover:opacity-30 pointer-events-none"
style={{
background: `radial-gradient(circle at ${progress}% 100%, ${accentColor}33 0%, transparent 60%)`
}}
/>
<div className="relative p-5 z-10">
{/* Top Section */}
<div className="flex gap-4 items-start mb-6">
<div className="relative h-14 w-14 shrink-0 overflow-hidden rounded-lg bg-zinc-800 shadow-inner flex items-center justify-center border border-white/5">
{coverUrl ? (
<img src={coverUrl} alt={title} className="h-full w-full object-cover" />
) : (
<Music2 className="text-zinc-600" size={24} />
)}
{/* Overlay Visualizer */}
<div className="absolute inset-x-0 bottom-1 flex justify-center gap-[2px] h-4">
{[0, 1, 2, 3, 4].map((i) => (
<motion.div
key={i}
custom={i}
variants={barVariants}
animate={isPlaying ? "playing" : "paused"}
className="w-[2px] bg-white rounded-full origin-bottom"
style={{ backgroundColor: isPlaying ? 'white' : 'rgba(255,255,255,0.3)' }}
/>
))}
</div>
</div>
<div className="flex flex-col min-w-0">
<h3 className="truncate text-lg font-bold tracking-tight text-white leading-tight">
{title}
</h3>
<p className="truncate text-sm font-medium text-zinc-400">
{artist}
</p>
</div>
<button className="ml-auto text-zinc-500 hover:text-white transition-colors">
<MoreHorizontal size={20} />
</button>
</div>
{/* Controls Section */}
<div className="flex items-center justify-between mb-6 px-1">
<div className="flex items-center gap-4 text-zinc-400">
<button className="hover:text-white hover:scale-110 transition-all">
<Volume2 size={18} />
</button>
</div>
<div className="flex items-center gap-6">
<motion.button
whileHover={{ scale: 1.1, x: -2 }}
whileTap={{ scale: 0.9 }}
className="text-white/70 hover:text-white"
>
<SkipBack size={22} fill="currentColor" />
</motion.button>
<motion.button
onClick={() => setIsPlaying(!isPlaying)}
whileHover={{ scale: 1.1 }}
whileTap={{ scale: 0.95 }}
className="flex h-12 w-12 items-center justify-center rounded-full bg-white text-black shadow-[0_0_20px_rgba(255,255,255,0.2)] transition-shadow hover:shadow-[0_0_25px_rgba(255,255,255,0.4)]"
>
{isPlaying ? <Pause size={24} fill="black" /> : <Play size={24} fill="black" className="ml-1" />}
</motion.button>
<motion.button
whileHover={{ scale: 1.1, x: 2 }}
whileTap={{ scale: 0.9 }}
className="text-white/70 hover:text-white"
>
<SkipForward size={22} fill="currentColor" />
</motion.button>
</div>
<motion.button
onClick={() => setIsLiked(!isLiked)}
whileHover={{ scale: 1.2 }}
whileTap={{ scale: 0.9 }}
className={cn(
"transition-colors",
isLiked ? "text-red-500" : "text-zinc-500 hover:text-white"
)}
>
<Heart size={20} fill={isLiked ? "currentColor" : "none"} />
</motion.button>
</div>
{/* Timeline Section */}
<div className="space-y-2">
<div className="relative h-1.5 w-full overflow-hidden rounded-full bg-zinc-800">
<motion.div
className="absolute inset-y-0 left-0 bg-white"
initial={{ width: 0 }}
animate={{ width: `${progress}%` }}
transition={{ duration: 0.5 }}
style={{
backgroundColor: isPlaying ? 'white' : '#71717a'
}}
/>
{/* Glow and handle hint */}
<div
className="absolute top-1/2 -translate-y-1/2 h-3 w-3 rounded-full bg-white shadow-[0_0_10px_white] opacity-0 group-hover:opacity-100 transition-opacity"
style={{ left: `calc(${progress}% - 6px)` }}
/>
</div>
<div className="flex justify-between text-[10px] font-medium tracking-tighter text-zinc-500 uppercase">
<span>1:31</span>
<span>3:46</span>
</div>
</div>
</div>
{/* Bottom Accent Line */}
<div
className="h-[2px] w-full origin-left bg-gradient-to-r from-transparent via-zinc-500 to-transparent opacity-20"
style={{ backgroundImage: `linear-gradient(to right, transparent, ${accentColor}, transparent)` }}
/>
</div>
)
}"use client"
import React, { useState } from "react"
import { motion, AnimatePresence } from "framer-motion"
import {
Play,
Pause,
SkipBack,
SkipForward,
Volume2,
Heart,
Music2,
MoreHorizontal
} from "lucide-react"
import { cn } from "@/lib/utils"
export const componentMeta = {
name: "Sonic Pulse Player",
description: "A premium glassmorphic media player with dynamic frequency visualizers and smooth animations.",
props: {
title: { type: "string", description: "Track title", default: '"Soldiers Rage"' },
artist: { type: "string", description: "Artist name", default: '"Tha Mechanic"' },
coverUrl: { type: "string", description: "URL for the album art", default: '""' },
accentColor: { type: "string", description: "Primary accent color", default: '"#6366f1"' }
}
}
export default function SonicPulseCard({
title = "Soldiers Rage",
artist = "Tha Mechanic",
coverUrl,
accentColor = "#6366f1", // Indigo-500
}: {
title?: string
artist?: string
coverUrl?: string
accentColor?: string
}) {
const [isPlaying, setIsPlaying] = useState(false)
const [progress, setProgress] = useState(42) // Percentage
const [isLiked, setIsLiked] = useState(false)
// Frequency bar animation variants
const barVariants: any = {
playing: (i: number) => ({
scaleY: [0.3, 1, 0.4, 0.8, 0.3],
transition: {
repeat: Infinity,
duration: 0.8,
delay: i * 0.15,
ease: "easeInOut",
},
}),
paused: {
scaleY: 0.1,
transition: { duration: 0.5, ease: "easeOut" }
}
}
return (
<div className="group relative w-full max-w-[320px] overflow-hidden rounded-2xl border border-white/10 bg-zinc-900/40 backdrop-blur-xl transition-all duration-500 hover:border-white/20 hover:shadow-[0_0_30px_rgba(0,0,0,0.5)]">
{/* Progress Glow Effect */}
<div
className="absolute inset-0 opacity-20 transition-opacity duration-1000 group-hover:opacity-30 pointer-events-none"
style={{
background: `radial-gradient(circle at ${progress}% 100%, ${accentColor}33 0%, transparent 60%)`
}}
/>
<div className="relative p-5 z-10">
{/* Top Section */}
<div className="flex gap-4 items-start mb-6">
<div className="relative h-14 w-14 shrink-0 overflow-hidden rounded-lg bg-zinc-800 shadow-inner flex items-center justify-center border border-white/5">
{coverUrl ? (
<img src={coverUrl} alt={title} className="h-full w-full object-cover" />
) : (
<Music2 className="text-zinc-600" size={24} />
)}
{/* Overlay Visualizer */}
<div className="absolute inset-x-0 bottom-1 flex justify-center gap-[2px] h-4">
{[0, 1, 2, 3, 4].map((i) => (
<motion.div
key={i}
custom={i}
variants={barVariants}
animate={isPlaying ? "playing" : "paused"}
className="w-[2px] bg-white rounded-full origin-bottom"
style={{ backgroundColor: isPlaying ? 'white' : 'rgba(255,255,255,0.3)' }}
/>
))}
</div>
</div>
<div className="flex flex-col min-w-0">
<h3 className="truncate text-lg font-bold tracking-tight text-white leading-tight">
{title}
</h3>
<p className="truncate text-sm font-medium text-zinc-400">
{artist}
</p>
</div>
<button className="ml-auto text-zinc-500 hover:text-white transition-colors">
<MoreHorizontal size={20} />
</button>
</div>
{/* Controls Section */}
<div className="flex items-center justify-between mb-6 px-1">
<div className="flex items-center gap-4 text-zinc-400">
<button className="hover:text-white hover:scale-110 transition-all">
<Volume2 size={18} />
</button>
</div>
<div className="flex items-center gap-6">
<motion.button
whileHover={{ scale: 1.1, x: -2 }}
whileTap={{ scale: 0.9 }}
className="text-white/70 hover:text-white"
>
<SkipBack size={22} fill="currentColor" />
</motion.button>
<motion.button
onClick={() => setIsPlaying(!isPlaying)}
whileHover={{ scale: 1.1 }}
whileTap={{ scale: 0.95 }}
className="flex h-12 w-12 items-center justify-center rounded-full bg-white text-black shadow-[0_0_20px_rgba(255,255,255,0.2)] transition-shadow hover:shadow-[0_0_25px_rgba(255,255,255,0.4)]"
>
{isPlaying ? <Pause size={24} fill="black" /> : <Play size={24} fill="black" className="ml-1" />}
</motion.button>
<motion.button
whileHover={{ scale: 1.1, x: 2 }}
whileTap={{ scale: 0.9 }}
className="text-white/70 hover:text-white"
>
<SkipForward size={22} fill="currentColor" />
</motion.button>
</div>
<motion.button
onClick={() => setIsLiked(!isLiked)}
whileHover={{ scale: 1.2 }}
whileTap={{ scale: 0.9 }}
className={cn(
"transition-colors",
isLiked ? "text-red-500" : "text-zinc-500 hover:text-white"
)}
>
<Heart size={20} fill={isLiked ? "currentColor" : "none"} />
</motion.button>
</div>
{/* Timeline Section */}
<div className="space-y-2">
<div className="relative h-1.5 w-full overflow-hidden rounded-full bg-zinc-800">
<motion.div
className="absolute inset-y-0 left-0 bg-white"
initial={{ width: 0 }}
animate={{ width: `${progress}%` }}
transition={{ duration: 0.5 }}
style={{
backgroundColor: isPlaying ? 'white' : '#71717a'
}}
/>
{/* Glow and handle hint */}
<div
className="absolute top-1/2 -translate-y-1/2 h-3 w-3 rounded-full bg-white shadow-[0_0_10px_white] opacity-0 group-hover:opacity-100 transition-opacity"
style={{ left: `calc(${progress}% - 6px)` }}
/>
</div>
<div className="flex justify-between text-[10px] font-medium tracking-tighter text-zinc-500 uppercase">
<span>1:31</span>
<span>3:46</span>
</div>
</div>
</div>
{/* Bottom Accent Line */}
<div
className="h-[2px] w-full origin-left bg-gradient-to-r from-transparent via-zinc-500 to-transparent opacity-20"
style={{ backgroundImage: `linear-gradient(to right, transparent, ${accentColor}, transparent)` }}
/>
</div>
)
}Save to favoritesCopy to Figma
React
Sonic Pulse Player
A premium glassmorphic media player with dynamic frequency visualizers and smooth animations.
Installation
$ npx @cosmoo/oblivion add sonic-pulse-cardDependencies
npm install framer-motion lucide-reactUsage Example
tsx
import SonicPulseCard from "@/components/oblivion/sonic-pulse-card"
export default function Demo() {
return (
<div className="p-10 flex justify-center">
<SonicPulseCard />
</div>
)
}import SonicPulseCard from "@/components/oblivion/sonic-pulse-card"
export default function Demo() {
return (
<div className="p-10 flex justify-center">
<SonicPulseCard />
</div>
)
}