Updated Frontend
This commit is contained in:
191
app/components/Hero.tsx
Normal file
191
app/components/Hero.tsx
Normal file
@@ -0,0 +1,191 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useRef, useCallback } from "react";
|
||||
import Link from "next/link";
|
||||
import gsap from "gsap";
|
||||
|
||||
const GRID_COLS = 20;
|
||||
const GRID_ROWS = 12;
|
||||
|
||||
function TileGrid() {
|
||||
const gridRef = useRef<HTMLDivElement>(null);
|
||||
const tilesRef = useRef<(HTMLDivElement | null)[]>([]);
|
||||
|
||||
const handleMouseEnter = useCallback((index: number) => {
|
||||
const tile = tilesRef.current[index];
|
||||
if (tile) {
|
||||
gsap.to(tile, {
|
||||
rotateY: 180,
|
||||
duration: 0.4,
|
||||
ease: "power2.out",
|
||||
});
|
||||
}
|
||||
}, []);
|
||||
|
||||
const handleMouseLeave = useCallback((index: number) => {
|
||||
const tile = tilesRef.current[index];
|
||||
if (tile) {
|
||||
gsap.to(tile, {
|
||||
rotateY: 0,
|
||||
duration: 0.4,
|
||||
ease: "power2.out",
|
||||
});
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={gridRef}
|
||||
className="absolute inset-0 grid z-0"
|
||||
style={{
|
||||
gridTemplateColumns: `repeat(${GRID_COLS}, 1fr)`,
|
||||
gridTemplateRows: `repeat(${GRID_ROWS}, 1fr)`,
|
||||
}}
|
||||
>
|
||||
{Array.from({ length: GRID_COLS * GRID_ROWS }).map((_, index) => (
|
||||
<div
|
||||
key={index}
|
||||
onMouseEnter={() => handleMouseEnter(index)}
|
||||
onMouseLeave={() => handleMouseLeave(index)}
|
||||
className="cursor-pointer"
|
||||
style={{ perspective: "500px" }}
|
||||
>
|
||||
<div
|
||||
ref={(el) => { tilesRef.current[index] = el; }}
|
||||
className="w-full h-full relative"
|
||||
style={{ transformStyle: "preserve-3d" }}
|
||||
>
|
||||
{/* Front - Black */}
|
||||
<div
|
||||
className="absolute inset-0 bg-black border border-zinc-900"
|
||||
style={{ backfaceVisibility: "hidden" }}
|
||||
/>
|
||||
{/* Back - White */}
|
||||
<div
|
||||
className="absolute inset-0 bg-white"
|
||||
style={{
|
||||
backfaceVisibility: "hidden",
|
||||
transform: "rotateY(180deg)",
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default function Hero() {
|
||||
const headingRef = useRef<HTMLHeadingElement>(null);
|
||||
const contentRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
// Animate heading on mount
|
||||
if (headingRef.current) {
|
||||
gsap.fromTo(
|
||||
headingRef.current,
|
||||
{ opacity: 0, y: 50 },
|
||||
{ opacity: 1, y: 0, duration: 1, ease: "power3.out", delay: 0.3 }
|
||||
);
|
||||
}
|
||||
|
||||
if (contentRef.current) {
|
||||
gsap.fromTo(
|
||||
contentRef.current.children,
|
||||
{ opacity: 0, y: 30 },
|
||||
{ opacity: 1, y: 0, duration: 0.8, stagger: 0.15, ease: "power3.out", delay: 0.5 }
|
||||
);
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<section className="relative min-h-screen bg-black overflow-hidden pt-28">
|
||||
{/* Tile Grid Background */}
|
||||
<TileGrid />
|
||||
|
||||
<div className="relative max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 h-full pointer-events-none">
|
||||
<div className="flex items-center justify-center min-h-[calc(100vh-12rem)] pb-20">
|
||||
{/* Center Content */}
|
||||
<div className="text-center relative z-10">
|
||||
<div className="inline-flex items-center gap-2 bg-lime-400 text-black px-5 py-2.5 text-xs font-bold tracking-widest rounded-full mb-10 pointer-events-auto">
|
||||
<span className="w-2 h-2 bg-black rounded-full animate-pulse" />
|
||||
FEBRUARY 2026
|
||||
</div>
|
||||
|
||||
<h1
|
||||
ref={headingRef}
|
||||
className="text-6xl sm:text-7xl lg:text-8xl xl:text-9xl font-black tracking-tighter text-white leading-[0.85] mb-8"
|
||||
style={{
|
||||
WebkitTextStroke: "2px black",
|
||||
paintOrder: "stroke fill",
|
||||
}}
|
||||
>
|
||||
<span className="block">UNLEASH</span>
|
||||
<span
|
||||
className="block text-lime-400 drop-shadow-[0_0_30px_rgba(163,230,53,0.5)]"
|
||||
style={{
|
||||
WebkitTextStroke: "2px black",
|
||||
paintOrder: "stroke fill",
|
||||
}}
|
||||
>
|
||||
YOUR ART
|
||||
</span>
|
||||
</h1>
|
||||
|
||||
<div ref={contentRef}>
|
||||
<p className="text-zinc-400 text-base sm:text-lg max-w-lg mx-auto mb-10 leading-relaxed font-light">
|
||||
From canvas to screen, showcase your creativity and let your
|
||||
artwork speak to the world.
|
||||
</p>
|
||||
|
||||
<div className="flex flex-col sm:flex-row gap-4 justify-center pointer-events-auto">
|
||||
<Link
|
||||
href="/register"
|
||||
className="inline-flex items-center justify-center gap-2 bg-lime-400 text-black px-10 py-4 text-sm font-bold tracking-wider hover:bg-lime-300 transition-all hover:scale-105 rounded-full shadow-[0_0_30px_rgba(163,230,53,0.3)]"
|
||||
>
|
||||
JOIN COMPETITION
|
||||
</Link>
|
||||
<Link
|
||||
href="/gallery"
|
||||
className="inline-flex items-center justify-center gap-2 bg-transparent text-white px-10 py-4 text-sm font-bold tracking-wider hover:bg-white/10 transition-all rounded-full border border-zinc-700 hover:border-zinc-500"
|
||||
>
|
||||
EXPLORE GALLERY
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Scroll Indicator - positioned above the marquee */}
|
||||
<div className="absolute bottom-28 left-1/2 -translate-x-1/2 flex flex-col items-center gap-2 text-zinc-500 z-10">
|
||||
<span className="text-[10px] tracking-[0.3em] uppercase">Scroll</span>
|
||||
<div className="w-px h-8 bg-gradient-to-b from-zinc-500 to-transparent" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Bottom Marquee */}
|
||||
<div className="absolute bottom-0 left-0 right-0 bg-lime-400 text-black py-3 overflow-hidden z-10">
|
||||
<div className="animate-marquee-slow whitespace-nowrap flex items-center">
|
||||
{Array(8)
|
||||
.fill(null)
|
||||
.map((_, i) => (
|
||||
<div key={i} className="flex items-center">
|
||||
<span className="text-xl sm:text-2xl font-black tracking-tight mx-6 uppercase">
|
||||
ArtSplash
|
||||
</span>
|
||||
<span className="text-black/40 mx-4">✦</span>
|
||||
<span className="text-xl sm:text-2xl font-black tracking-tight mx-6 uppercase text-black/60">
|
||||
SJEC
|
||||
</span>
|
||||
<span className="text-black/40 mx-4">✦</span>
|
||||
<span className="text-xl sm:text-2xl font-black tracking-tight mx-6 uppercase">
|
||||
2026
|
||||
</span>
|
||||
<span className="text-black/40 mx-4">✦</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user