diff --git a/web/src/components/hero.tsx b/web/src/components/hero.tsx index 6e4794fc..4020f2da 100644 --- a/web/src/components/hero.tsx +++ b/web/src/components/hero.tsx @@ -4,10 +4,10 @@ import { Button } from "@/components/ui/button" import { Card } from "@/components/ui/card" import { Input } from "@/components/ui/input" import { cn } from "@/lib/utils" -import { motion, useAnimation } from "framer-motion" +import { motion, useAnimation, useInView } from "framer-motion" import { Circle, Github, Heart, Search, Sparkles } from "lucide-react" import Link from "next/link" -import { useEffect, useState } from "react" +import { useEffect, useState, useRef } from "react" interface IconCardProps { name: string @@ -46,6 +46,8 @@ function ElegantShape({ }) { const controls = useAnimation() const [isMobile, setIsMobile] = useState(false) + const ref = useRef(null) + const isInView = useInView(ref, { once: true, amount: 0.1 }) useEffect(() => { const checkMobile = () => { @@ -56,40 +58,51 @@ function ElegantShape({ return () => window.removeEventListener("resize", checkMobile) }, []) + useEffect(() => { + if (isInView) { + controls.start({ + opacity: 1, + y: 0, + rotate: rotate, + transition: { + type: "spring", + stiffness: 50, + damping: 20, + duration: 1.8, + delay, + ease: [0.23, 0.86, 0.39, 0.96], + opacity: { duration: 1.2 }, + } + }) + } + }, [controls, delay, isInView, rotate]) + return (
- {icons.map(({ name, data }, index) => ( + {icons.map(({ name, data }) => ( + + ))} +
+ + + View all icons + + + +
+ + ) +} + +// Extracted component for better animation handling +function RecentIconCard({ name, data, getIconVariant }: { + name: string; + data: any; + getIconVariant: (name: string, data: any) => string; +}) { + const ref = useRef(null); + const isInView = useInView(ref, { + once: false, + amount: 0.2, + margin: "100px 0px" + }); + + const variants = { + hidden: { opacity: 0, y: 20, scale: 0.95 }, + visible: { + opacity: 1, + y: 0, + scale: 1, + transition: { duration: 0.4, ease: [0.25, 0.1, 0.25, 1.0] } + }, + exit: { + opacity: 0, + y: -10, + scale: 0.98, + transition: { duration: 0.3, ease: [0.25, 0.1, 0.25, 1.0] } + } + }; + + return ( + - ))} - - - - - View all icons - - - - - - ) + ); }