Import source: src/components/NewReleases/NewReleases
Import the existing local project snapshot. This commit organizes existing files; it does not represent newly developed functionality.
This commit is contained in:
@@ -0,0 +1,128 @@
|
||||
import { useRef } from 'react'
|
||||
import { motion } from 'framer-motion'
|
||||
import { Canvas, useFrame } from '@react-three/fiber'
|
||||
|
||||
const releases = [
|
||||
{ id: 1, title: 'Singularity', artist: 'AURA', label: 'New', cover: 'https://picsum.photos/seed/nr1/400/400', duration: '38 min' },
|
||||
{ id: 2, title: 'Phase IV', artist: 'The Void', label: 'Single', cover: 'https://picsum.photos/seed/nr2/400/400', duration: '4:12' },
|
||||
{ id: 3, title: 'Lightspeed', artist: 'Echo System', label: 'EP', cover: 'https://picsum.photos/seed/nr3/400/400', duration: '22 min' },
|
||||
{ id: 4, title: 'Aperture', artist: 'Parallax', label: 'New', cover: 'https://picsum.photos/seed/nr4/400/400', duration: '51 min' },
|
||||
{ id: 5, title: 'Nocturne', artist: 'Solaris', label: 'Single', cover: 'https://picsum.photos/seed/nr5/400/400', duration: '5:04' },
|
||||
{ id: 6, title: 'Tessellate', artist: 'Dark Matter', label: 'Album', cover: 'https://picsum.photos/seed/nr6/400/400', duration: '44 min' },
|
||||
]
|
||||
|
||||
function SpinningDisc() {
|
||||
const outerRef = useRef()
|
||||
const innerRef = useRef()
|
||||
useFrame((_, delta) => {
|
||||
outerRef.current.rotation.z += delta * 0.3
|
||||
innerRef.current.rotation.z -= delta * 0.5
|
||||
})
|
||||
return (
|
||||
<group>
|
||||
<mesh ref={outerRef}>
|
||||
<torusGeometry args={[1.8, 0.04, 12, 80]} />
|
||||
<meshStandardMaterial color="#c9a84c" emissive="#c9a84c" emissiveIntensity={0.4} roughness={0.1} metalness={1} />
|
||||
</mesh>
|
||||
<mesh ref={innerRef}>
|
||||
<torusGeometry args={[1.2, 0.025, 12, 80]} />
|
||||
<meshStandardMaterial color="#e8c547" emissive="#e8c547" emissiveIntensity={0.3} roughness={0.1} metalness={1} />
|
||||
</mesh>
|
||||
<mesh>
|
||||
<cylinderGeometry args={[0.55, 0.55, 0.06, 48]} />
|
||||
<meshStandardMaterial color="#1a1a1a" roughness={0.5} metalness={0.6} />
|
||||
</mesh>
|
||||
<mesh>
|
||||
<torusGeometry args={[0.55, 0.02, 8, 48]} />
|
||||
<meshBasicMaterial color="#c9a84c" transparent opacity={0.6} />
|
||||
</mesh>
|
||||
</group>
|
||||
)
|
||||
}
|
||||
|
||||
function ReleaseCard({ release, index }) {
|
||||
const label = { 'New': '#c9a84c', 'Single': '#8a6f2e', 'EP': '#6b5a25', 'Album': '#c9a84c' }
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, x: 40 }}
|
||||
whileInView={{ opacity: 1, x: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.5, delay: index * 0.08 }}
|
||||
whileHover={{ y: -6, scale: 1.02 }}
|
||||
className="flex-shrink-0 cursor-pointer group"
|
||||
style={{ width: '200px' }}
|
||||
>
|
||||
<div className="relative rounded-xl overflow-hidden mb-3" style={{ aspectRatio: '1' }}>
|
||||
<img src={release.cover} alt={release.title} className="w-full h-full object-cover transition-transform duration-500 group-hover:scale-110" />
|
||||
<div className="absolute inset-0" style={{ background: 'linear-gradient(to top, rgba(8,8,8,0.8) 0%, transparent 60%)' }} />
|
||||
|
||||
{/* Label badge */}
|
||||
<div className="absolute top-2.5 left-2.5 px-2 py-0.5 rounded-full text-xs font-medium"
|
||||
style={{ background: `${label[release.label]}22`, border: `1px solid ${label[release.label]}55`, color: label[release.label] }}>
|
||||
{release.label}
|
||||
</div>
|
||||
|
||||
{/* Play on hover */}
|
||||
<div className="absolute inset-0 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity duration-300">
|
||||
<div className="w-12 h-12 rounded-full flex items-center justify-center"
|
||||
style={{ background: 'linear-gradient(135deg, #c9a84c, #e8c547)' }}>
|
||||
<svg className="w-4 h-4 ml-0.5" fill="#080808" viewBox="0 0 24 24"><path d="M8 5v14l11-7z" /></svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h4 className="font-display font-semibold text-white text-sm truncate group-hover:gold-text transition-colors">{release.title}</h4>
|
||||
<p className="text-xs text-gray-600 mt-0.5">{release.artist} · {release.duration}</p>
|
||||
</motion.div>
|
||||
)
|
||||
}
|
||||
|
||||
export default function NewReleases() {
|
||||
const scrollRef = useRef()
|
||||
|
||||
return (
|
||||
<section className="py-28" style={{ background: '#0d0d0d', overflow: 'hidden' }}>
|
||||
<div className="section-divider" />
|
||||
|
||||
<div className="max-w-7xl mx-auto px-6 mt-14">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-12 items-center mb-14">
|
||||
{/* Vinyl 3D */}
|
||||
<div className="hidden lg:block" style={{ height: '260px' }}>
|
||||
<Canvas camera={{ position: [0, 1.5, 5], fov: 48 }} gl={{ alpha: true, antialias: true }} style={{ background: 'transparent' }}>
|
||||
<ambientLight intensity={0.15} />
|
||||
<pointLight position={[3, 3, 3]} intensity={3} color="#c9a84c" />
|
||||
<pointLight position={[-3, -2, 2]} intensity={1.5} color="#e8c547" />
|
||||
<SpinningDisc />
|
||||
</Canvas>
|
||||
</div>
|
||||
|
||||
{/* Heading */}
|
||||
<div className="lg:col-span-2">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.6 }}
|
||||
>
|
||||
<p className="text-xs tracking-[0.25em] uppercase gold-text mb-3">Fresh Drops</p>
|
||||
<h2 className="font-display font-bold text-4xl md:text-5xl text-white mb-4">
|
||||
New <span className="gold-text">Releases</span>
|
||||
</h2>
|
||||
<p className="text-gray-600 text-sm max-w-md">The latest from the artists shaping the sound of tomorrow. Updated every Friday.</p>
|
||||
</motion.div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Horizontal scroll */}
|
||||
<div
|
||||
ref={scrollRef}
|
||||
className="flex gap-5 overflow-x-auto pb-4"
|
||||
style={{ scrollbarWidth: 'none', msOverflowStyle: 'none' }}
|
||||
>
|
||||
{releases.map((r, i) => <ReleaseCard key={r.id} release={r} index={i} />)}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user