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:
arsam
2026-09-18 23:08:03 +03:30
parent 5c9689a224
commit 397588dff2
+128
View File
@@ -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>
)
}