Spaces:
Build error
Build error
File size: 7,941 Bytes
438f64f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 | import { useEffect, useRef } from 'react';
import { gsap } from 'gsap';
import { ArrowDown, Play, Sparkles, Terminal } from 'lucide-react';
export default function Hero() {
const heroRef = useRef(null);
const titleRef = useRef(null);
const subtitleRef = useRef(null);
const ctaRef = useRef(null);
const canvasRef = useRef(null);
useEffect(() => {
// Binary rain animation
const canvas = canvasRef.current;
const ctx = canvas.getContext('2d');
let animationId;
const resize = () => {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
};
resize();
window.addEventListener('resize', resize);
const chars = '01γ’γ€γ¦γ¨γͺγ«γγ―γ±γ³γ΅γ·γΉγ»γ½γΏγγγγγγγγγγγγγγγγγ γ‘γ’γ€γ¦γ¨γ©γͺγ«γ¬γγ―γ²γ³';
const fontSize = 14;
const columns = canvas.width / fontSize;
const drops = Array(Math.floor(columns)).fill(1);
const draw = () => {
ctx.fillStyle = 'rgba(10, 10, 15, 0.05)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = '#00f0ff';
ctx.font = `${fontSize}px JetBrains Mono`;
drops.forEach((drop, i) => {
const char = chars[Math.floor(Math.random() * chars.length)];
ctx.fillText(char, i * fontSize, drop * fontSize);
drops[i] = drop * fontSize > canvas.height && Math.random() > 0.975 ? 0 : drop + 1;
});
};
const animate = () => {
draw();
animationId = requestAnimationFrame(animate);
};
animate();
// GSAP Animations
const tl = gsap.timeline({ defaults: { ease: 'power4.out' } });
tl.from('.hero-badge', {
y: 30,
opacity: 0,
duration: 0.8,
})
.from(titleRef.current, {
y: 100,
opacity: 0,
duration: 1,
skewY: 7,
}, '-=0.4')
.from(subtitleRef.current, {
y: 50,
opacity: 0,
duration: 0.8,
}, '-=0.6')
.from('.hero-stats', {
y: 30,
opacity: 0,
duration: 0.6,
stagger: 0.1,
}, '-=0.4')
.from(ctaRef.current, {
y: 30,
opacity: 0,
duration: 0.6,
}, '-=0.3');
// Floating elements animation
gsap.to('.float-element', {
y: -20,
rotation: 5,
duration: 3,
ease: 'sine.inOut',
yoyo: true,
repeat: -1,
stagger: 0.5,
});
return () => {
cancelAnimationFrame(animationId);
window.removeEventListener('resize', resize);
};
}, []);
const scrollToWorkbench = () => {
document.getElementById('workbench').scrollIntoView({ behavior: 'smooth' });
};
return (
<section ref={heroRef} className="relative min-h-screen flex items-center justify-center overflow-hidden pt-20">
{/* Binary Rain Canvas */}
<canvas ref={canvasRef} className="absolute inset-0 pointer-events-none opacity-30" />
{/* Gradient Orbs */}
<div className="absolute top-1/4 left-1/4 w-96 h-96 bg-electric-500/20 rounded-full blur-3xl animate-pulse-slow" />
<div className="absolute bottom-1/4 right-1/4 w-96 h-96 bg-magma-500/20 rounded-full blur-3xl animate-pulse-slow" style={{ animationDelay: '1s' }} />
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[600px] h-[600px] bg-gold-500/10 rounded-full blur-3xl animate-pulse-slow" style={{ animationDelay: '2s' }} />
{/* Grid Pattern */}
<div className="absolute inset-0 grid-pattern opacity-50" />
{/* Floating Code Elements */}
<div className="absolute left-10 top-1/3 float-element hidden lg:block">
<div className="bg-iron-800/80 backdrop-blur-sm border border-iron-600/50 rounded-lg p-4 font-mono text-xs text-electric-400">
<div className="flex items-center gap-2 mb-2 text-iron-400">
<Terminal className="w-4 h-4" />
<span>bash</span>
</div>
<p className="terminal-cursor">npm run optimize</p>
</div>
</div>
<div className="absolute right-10 top-1/2 float-element hidden lg:block" style={{ animationDelay: '0.5s' }}>
<div className="bg-iron-800/80 backdrop-blur-sm border border-iron-600/50 rounded-lg p-4 font-mono text-xs text-magma-400">
<p>{`{`}</p>
<p className="pl-2">"performance": "99.9%",</p>
<p className="pl-2">"optimization": "complete"</p>
<p>{`}`}</p>
</div>
</div>
<div className="absolute left-20 bottom-1/3 float-element hidden lg:block" style={{ animationDelay: '1s' }}>
<div className="bg-iron-800/80 backdrop-blur-sm border border-iron-600/50 rounded-lg p-3 font-mono text-xs text-gold-400">
<Sparkles className="w-4 h-4 mb-1" />
<p>AI Enhanced</p>
</div>
</div>
{/* Main Content */}
<div className="relative z-10 max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
{/* Badge */}
<div className="hero-badge inline-flex items-center gap-2 px-4 py-2 rounded-full bg-iron-800/80 border border-electric-500/30 mb-8">
<span className="w-2 h-2 bg-electric-500 rounded-full animate-pulse" />
<span className="font-mono text-sm text-electric-400">SYSTEM ONLINE v2.024</span>
</div>
{/* Title */}
<h1 ref={titleRef} className="text-5xl sm:text-7xl lg:text-8xl font-bold mb-6 tracking-tight">
<span className="block text-iron-100 glitch" data-text="FORGE YOUR">FORGE YOUR</span>
<span className="block text-gradient">DIGITAL EDGE</span>
</h1>
{/* Subtitle */}
<p ref={subtitleRef} className="max-w-2xl mx-auto text-lg sm:text-xl text-iron-300 mb-12 font-mono leading-relaxed">
Advanced protocols for developers who refuse to settle.
Master the arcane arts of performance, automation, and system architecture.
</p>
{/* Stats */}
<div className="flex flex-wrap justify-center gap-8 mb-12">
{[
{ value: '500+', label: 'Pro Tips' },
{ value: '50K+', label: 'Developers' },
{ value: '99.9%', label: 'Uptime' },
].map((stat, i) => (
<div key={i} className="hero-stats text-center">
<div className="text-3xl sm:text-4xl font-bold text-electric-500 font-mono">{stat.value}</div>
<div className="text-sm text-iron-400 font-mono uppercase tracking-wider">{stat.label}</div>
</div>
))}
</div>
{/* CTA Buttons */}
<div ref={ctaRef} className="flex flex-col sm:flex-row gap-4 justify-center">
<button
onClick={scrollToWorkbench}
className="group relative px-8 py-4 bg-gradient-to-r from-electric-500 to-electric-400 text-iron-900 font-mono font-semibold rounded-lg overflow-hidden transition-all hover:scale-105"
>
<span className="relative z-10 flex items-center justify-center gap-2">
<Play className="w-5 h-5" />
ENTER THE LAB
</span>
<div className="absolute inset-0 bg-gradient-to-r from-magma-500 to-electric-500 opacity-0 group-hover:opacity-100 transition-opacity duration-500" />
</button>
<button className="group px-8 py-4 border border-iron-600 text-iron-200 font-mono font-semibold rounded-lg hover:border-electric-500 hover:text-electric-500 transition-all flex items-center justify-center gap-2">
<ArrowDown className="w-5 h-5 group-hover:translate-y-1 transition-transform" />
EXPLORE ARCHIVE
</button>
</div>
</div>
{/* Scroll Indicator */}
<div className="absolute bottom-8 left-1/2 -translate-x-1/2">
<div className="w-6 h-10 border-2 border-iron-600 rounded-full flex justify-center pt-2">
<div className="w-1.5 h-3 bg-electric-500 rounded-full animate-bounce" />
</div>
</div>
</section>
);
} |