264 lines
11 KiB
TypeScript
264 lines
11 KiB
TypeScript
'use client';
|
|
|
|
import Link from 'next/link';
|
|
import { useEffect, useRef, useState } from 'react';
|
|
import styles from './Hero.module.css';
|
|
|
|
export default function Hero() {
|
|
const canvasRef = useRef<HTMLCanvasElement>(null);
|
|
const heroRef = useRef<HTMLDivElement>(null);
|
|
const [typedText, setTypedText] = useState('');
|
|
const [cursorTrail, setCursorTrail] = useState<Array<{ x: number; y: number; id: number }>>([]);
|
|
const [stats, setStats] = useState({ users: 0, posts: 0, rating: 0 });
|
|
|
|
const fullText = 'Manage All Your Social Media in One Place';
|
|
|
|
// Typing animation
|
|
useEffect(() => {
|
|
let index = 0;
|
|
const timer = setInterval(() => {
|
|
if (index <= fullText.length) {
|
|
setTypedText(fullText.slice(0, index));
|
|
index++;
|
|
} else {
|
|
clearInterval(timer);
|
|
}
|
|
}, 50);
|
|
return () => clearInterval(timer);
|
|
}, []);
|
|
|
|
// Stats counter animation
|
|
useEffect(() => {
|
|
const duration = 2000;
|
|
const steps = 60;
|
|
const interval = duration / steps;
|
|
let step = 0;
|
|
|
|
const timer = setInterval(() => {
|
|
step++;
|
|
const progress = step / steps;
|
|
setStats({
|
|
users: Math.floor(10000 * progress),
|
|
posts: Math.floor(1000000 * progress),
|
|
rating: Math.min(4.9, 4.9 * progress),
|
|
});
|
|
|
|
if (step >= steps) clearInterval(timer);
|
|
}, interval);
|
|
|
|
return () => clearInterval(timer);
|
|
}, []);
|
|
|
|
|
|
// Enhanced particle system - Cleaner & Performance Optimized
|
|
useEffect(() => {
|
|
const canvas = canvasRef.current;
|
|
if (!canvas) return;
|
|
|
|
const ctx = canvas.getContext('2d');
|
|
if (!ctx) return;
|
|
|
|
canvas.width = window.innerWidth;
|
|
canvas.height = window.innerHeight;
|
|
|
|
const particles: Array<{
|
|
x: number;
|
|
y: number;
|
|
size: number;
|
|
speedX: number;
|
|
speedY: number;
|
|
color: string;
|
|
opacity: number;
|
|
}> = [];
|
|
|
|
// Reduced particle count for a cleaner look
|
|
for (let i = 0; i < 60; i++) {
|
|
const colors = [
|
|
'rgba(236, 72, 153, 0.4)', // Pink
|
|
'rgba(59, 130, 246, 0.4)', // Blue
|
|
'rgba(255, 255, 255, 0.1)', // White
|
|
];
|
|
particles.push({
|
|
x: Math.random() * canvas.width,
|
|
y: Math.random() * canvas.height,
|
|
size: Math.random() * 2 + 1, // Smaller particles
|
|
speedX: Math.random() * 0.5 - 0.25, // Slower movement
|
|
speedY: Math.random() * 0.5 - 0.25,
|
|
color: colors[Math.floor(Math.random() * colors.length)],
|
|
opacity: Math.random() * 0.5 + 0.1,
|
|
});
|
|
}
|
|
|
|
function animate() {
|
|
if (!ctx || !canvas) return;
|
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
|
|
// Draw connections - very subtle
|
|
particles.forEach((particle, i) => {
|
|
particles.slice(i + 1).forEach((otherParticle) => {
|
|
const dx = particle.x - otherParticle.x;
|
|
const dy = particle.y - otherParticle.y;
|
|
const distance = Math.sqrt(dx * dx + dy * dy);
|
|
|
|
if (distance < 100) {
|
|
ctx.beginPath();
|
|
ctx.strokeStyle = `rgba(255, 255, 255, ${0.05 * (1 - distance / 100)})`;
|
|
ctx.lineWidth = 0.5;
|
|
ctx.moveTo(particle.x, particle.y);
|
|
ctx.lineTo(otherParticle.x, otherParticle.y);
|
|
ctx.stroke();
|
|
}
|
|
});
|
|
});
|
|
|
|
// Draw particles
|
|
particles.forEach((particle) => {
|
|
ctx.globalAlpha = particle.opacity;
|
|
ctx.fillStyle = particle.color;
|
|
ctx.beginPath();
|
|
ctx.arc(particle.x, particle.y, particle.size, 0, Math.PI * 2);
|
|
ctx.fill();
|
|
|
|
// Update position
|
|
particle.x += particle.speedX;
|
|
particle.y += particle.speedY;
|
|
|
|
if (particle.x < 0 || particle.x > canvas.width) particle.speedX *= -1;
|
|
if (particle.y < 0 || particle.y > canvas.height) particle.speedY *= -1;
|
|
});
|
|
|
|
requestAnimationFrame(animate);
|
|
}
|
|
|
|
animate();
|
|
|
|
const handleResize = () => {
|
|
canvas.width = window.innerWidth;
|
|
canvas.height = window.innerHeight;
|
|
};
|
|
|
|
window.addEventListener('resize', handleResize);
|
|
return () => window.removeEventListener('resize', handleResize);
|
|
}, []);
|
|
|
|
return (
|
|
<section className={styles.hero} ref={heroRef}>
|
|
<canvas ref={canvasRef} className={styles.canvas} />
|
|
|
|
{/* Floating gradient orbs */}
|
|
<div className={styles.gradientOrb1} />
|
|
<div className={styles.gradientOrb2} />
|
|
<div className={styles.gradientOrb3} />
|
|
|
|
{/* Morphing shapes */}
|
|
<div className={styles.morphingShape1}></div>
|
|
<div className={styles.morphingShape2}></div>
|
|
|
|
<div className="container">
|
|
<div className={styles.heroContent}>
|
|
<div className={styles.textContent}>
|
|
<div className={styles.badge}>
|
|
<span className={styles.badgeIcon}>✨</span>
|
|
<span>Scale your Social Media Presence</span>
|
|
<span className={styles.badgePulse}></span>
|
|
</div>
|
|
|
|
<h1 className={styles.title}>
|
|
<span className={styles.typingText}>
|
|
{typedText}
|
|
<span className={styles.cursor}>|</span>
|
|
</span>
|
|
</h1>
|
|
|
|
<p className={`${styles.subtitle} animate-fade-in`}>
|
|
Empower your brand with intelligent scheduling, deep analytics, and real-time engagement tools.
|
|
</p>
|
|
|
|
<div className={`${styles.ctaButtons} animate-fade-in`}>
|
|
<a href="https://app.socialbuddy.co/signup" className={styles.primaryCta}>
|
|
<span>Start Free Trial</span>
|
|
<span className={styles.arrow}>→</span>
|
|
<span className={styles.buttonGlow}></span>
|
|
</a>
|
|
<Link href="/demo" className={styles.secondaryCta}>
|
|
<span className={styles.playIcon}>▶</span>
|
|
<span>Watch Demo</span>
|
|
</Link>
|
|
</div>
|
|
|
|
<div className={styles.trustBadges}>
|
|
<div className={styles.trustBadge}>
|
|
<div className={styles.trustValue}>{stats.rating.toFixed(1)}/5</div>
|
|
<div className={styles.trustLabel}>Rating</div>
|
|
</div>
|
|
<div className={styles.trustBadge}>
|
|
<div className={styles.trustValue}>{(stats.users / 1000).toFixed(0)}K+</div>
|
|
<div className={styles.trustLabel}>Active Users</div>
|
|
</div>
|
|
<div className={styles.trustBadge}>
|
|
<div className={styles.trustValue}>{(stats.posts / 1000000).toFixed(1)}M+</div>
|
|
<div className={styles.trustLabel}>Posts Scheduled</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div className={styles.imageContent}>
|
|
<div className={styles.dashboardPreview}>
|
|
{/* Floating social media icons */}
|
|
<div className={`${styles.floatingIcon} ${styles.icon1}`}>
|
|
<span>📱</span>
|
|
</div>
|
|
<div className={`${styles.floatingIcon} ${styles.icon2}`}>
|
|
<span>📊</span>
|
|
</div>
|
|
<div className={`${styles.floatingIcon} ${styles.icon3}`}>
|
|
<span>💬</span>
|
|
</div>
|
|
|
|
<div className={styles.previewHeader}>
|
|
<div className={styles.previewDots}>
|
|
<span></span>
|
|
<span></span>
|
|
<span></span>
|
|
</div>
|
|
<div className={styles.previewTitle}>SocialBuddy Dashboard</div>
|
|
</div>
|
|
<div className={styles.previewBody}>
|
|
<div className={`${styles.previewCard} ${styles.analyticsCard}`}>
|
|
<div className={styles.cardHeader}>
|
|
<span>📊</span>
|
|
<span>Analytics Overview</span>
|
|
</div>
|
|
<div className={styles.cardContent}>
|
|
<div className={styles.chartBar}></div>
|
|
<div className={styles.chartBar}></div>
|
|
<div className={styles.chartBar}></div>
|
|
</div>
|
|
</div>
|
|
<div className={`${styles.previewCard} ${styles.scheduleCard}`}>
|
|
<div className={styles.cardHeader}>
|
|
<span>📅</span>
|
|
<span>Upcoming Posts</span>
|
|
</div>
|
|
<div className={styles.cardContent}>
|
|
<div className={styles.scheduleItem}></div>
|
|
<div className={styles.scheduleItem}></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Enhanced scroll indicator */}
|
|
<div className={styles.scrollIndicator}>
|
|
<div className={styles.mouse}>
|
|
<div className={styles.mouseWheel}></div>
|
|
</div>
|
|
<span>Scroll</span>
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|