Oblivion
Oblivion
Docs
Go back
Component by
OV
Oblivion

Soldiers 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>
  )
}
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-card
Dependenciesnpm install framer-motion lucide-react

Usage Example

tsx
import SonicPulseCard from "@/components/oblivion/sonic-pulse-card"

export default function Demo() {
  return (
    <div className="p-10 flex justify-center">
      <SonicPulseCard />
    </div>
  )
}