Import source: src/components/MoodSection/MoodSection

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:01 +03:30
parent 3fc7b54404
commit 071a5e7110
+139
View File
@@ -0,0 +1,139 @@
import { useRef } from 'react'
import { Canvas, useFrame } from '@react-three/fiber'
import { motion } from 'framer-motion'
import * as THREE from 'three'
const moods = [
{ name: 'Focus', desc: 'Deep concentration', tracks: 284, emoji: '◉' },
{ name: 'Chill', desc: 'Ease into the day', tracks: 512, emoji: '◎' },
{ name: 'Energy', desc: 'Push your limits', tracks: 389, emoji: '◈' },
{ name: 'Sleep', desc: 'Drift into calm', tracks: 156, emoji: '◐' },
{ name: 'Hype', desc: 'Turn it all up', tracks: 441, emoji: '◆' },
{ name: 'Melancholy', desc: 'Feel every note', tracks: 203, emoji: '◑' },
]
function NeuralWeb() {
const groupRef = useRef()
const nodesRef = useRef([])
const lineRefs = useRef([])
const nodePositions = [
[-2, 1, 0], [0, 1.5, 0.5], [2, 0.8, -0.3],
[-1.5, -0.5, 0.3], [0.5, -1, 0], [2.2, -0.8, 0.4],
[-2.5, 0, -0.2], [1, 0.2, 1],
]
useFrame(({ clock }) => {
const t = clock.getElapsedTime()
if (groupRef.current) groupRef.current.rotation.y = t * 0.1
nodesRef.current.forEach((mesh, i) => {
if (!mesh) return
mesh.position.y = nodePositions[i][1] + Math.sin(t * 0.6 + i) * 0.12
const s = 0.06 + Math.abs(Math.sin(t * 0.8 + i * 0.7)) * 0.04
mesh.scale.setScalar(s)
})
})
const linePairs = [[0,1],[1,2],[2,5],[0,3],[3,4],[4,5],[1,7],[7,4],[0,6],[6,3],[1,3],[2,7]]
return (
<group ref={groupRef}>
{nodePositions.map((pos, i) => (
<mesh key={i} ref={el => nodesRef.current[i] = el} position={pos}>
<sphereGeometry args={[1, 12, 12]} />
<meshStandardMaterial color="#c9a84c" emissive="#c9a84c" emissiveIntensity={0.6} roughness={0.1} metalness={0.9} toneMapped={false} />
</mesh>
))}
{linePairs.map(([a, b], i) => {
const pa = new THREE.Vector3(...nodePositions[a])
const pb = new THREE.Vector3(...nodePositions[b])
const mid = pa.clone().add(pb).multiplyScalar(0.5)
const dir = pb.clone().sub(pa)
const len = dir.length()
const quat = new THREE.Quaternion()
quat.setFromUnitVectors(new THREE.Vector3(0,1,0), dir.normalize())
return (
<mesh key={i} position={mid} quaternion={quat}>
<cylinderGeometry args={[0.006, 0.006, len, 4]} />
<meshBasicMaterial color="#c9a84c" transparent opacity={0.2} />
</mesh>
)
})}
</group>
)
}
function MoodCard({ mood, index }) {
return (
<motion.div
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5, delay: index * 0.08 }}
whileHover={{ y: -5, scale: 1.03 }}
className="relative cursor-pointer group rounded-2xl p-5 flex flex-col gap-3"
style={{ background: '#101010', border: '1px solid #1e1e1e' }}
>
<div className="absolute inset-0 rounded-2xl opacity-0 group-hover:opacity-100 transition-all duration-300"
style={{ boxShadow: 'inset 0 0 0 1px rgba(201,168,76,0.2), 0 0 25px rgba(201,168,76,0.06)' }} />
<div className="flex items-center justify-between">
<span className="text-xl" style={{ color: 'rgba(201,168,76,0.7)' }}>{mood.emoji}</span>
<span className="text-xs text-gray-700 font-mono">{mood.tracks} tracks</span>
</div>
<div>
<h3 className="font-display font-semibold text-white text-base group-hover:gold-text transition-colors">{mood.name}</h3>
<p className="text-xs text-gray-600 mt-0.5">{mood.desc}</p>
</div>
<div className="flex gap-1 mt-1">
{Array.from({ length: 12 }, (_, i) => (
<div key={i} className="flex-1 rounded-full group-hover:opacity-100 opacity-30 transition-all duration-300"
style={{ height: `${6 + Math.abs(Math.sin(i * 1.2)) * 10}px`, background: '#c9a84c', transitionDelay: `${i * 20}ms` }} />
))}
</div>
</motion.div>
)
}
export default function MoodSection() {
return (
<section className="py-28 px-6" style={{ background: '#080808' }}>
<div className="section-divider" />
<div className="max-w-7xl mx-auto">
<div className="grid grid-cols-1 lg:grid-cols-5 gap-16 items-center mt-14">
{/* Moods grid */}
<div className="lg:col-span-3">
<motion.div
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.6 }}
className="mb-10"
>
<p className="text-xs tracking-[0.25em] uppercase gold-text mb-3">Curated For You</p>
<h2 className="font-display font-bold text-4xl md:text-5xl text-white">
Match Your <span className="gold-text">Mood</span>
</h2>
</motion.div>
<div className="grid grid-cols-2 md:grid-cols-3 gap-3">
{moods.map((mood, i) => <MoodCard key={mood.name} mood={mood} index={i} />)}
</div>
</div>
{/* 3D Neural web */}
<div className="lg:col-span-2 hidden lg:block" style={{ height: '400px' }}>
<Canvas camera={{ position: [0, 0, 7], fov: 52 }} gl={{ alpha: true, antialias: true }} style={{ background: 'transparent' }}>
<ambientLight intensity={0.08} />
<pointLight position={[0, 4, 4]} intensity={4} color="#c9a84c" />
<pointLight position={[-4, -2, 2]} intensity={2} color="#e8c547" />
<NeuralWeb />
</Canvas>
</div>
</div>
</div>
</section>
)
}