diff --git a/src/components/typewriter-effect.jsx b/src/components/typewriter-effect.jsx new file mode 100644 index 0000000..44cf2f3 --- /dev/null +++ b/src/components/typewriter-effect.jsx @@ -0,0 +1,81 @@ +import { cn } from "@/lib/utils"; +import { motion, stagger, useAnimate, useInView } from "framer-motion"; +import { useEffect } from "react"; +import { FaStar } from "react-icons/fa"; + +export const TypewriterEffect = ({ + words, + className, + cursorClassName, + setCursorVariant, +}) => { + // split text inside of words into array of characters + const wordsArray = words.map((word) => { + return { + ...word, + text: word.text.split(""), + }; + }); + + const [scope, animate] = useAnimate(); + const isInView = useInView(scope); + useEffect(() => { + if (isInView) { + animate( + "span", + { + display: "inline-block", + opacity: 1, + width: "fit-content", + }, + { + duration: 0.3, + delay: stagger(0.1), + ease: "easeInOut", + }, + ); + } + }, [isInView]); + + const renderWords = () => { + return ( + + {wordsArray.map((word, idx) => { + const wordClassName = cn( + `text-foreground opacity-0 hidden`, + word.className, + ); + const isPrimary = + word.className && word.className.includes("primary"); + const spanProps = { + initial: {}, + className: wordClassName, + }; + if (isPrimary) { + spanProps.onMouseEnter = handleMouseEnter; + spanProps.onMouseLeave = handleMouseLeave; + } + return ( +
+ {word.text.map((char, index) => ( + + {char} + + ))} +   +
+ ); + })} +
+ ); + }; + + const handleMouseEnter = () => setCursorVariant("bigText"); + const handleMouseLeave = () => setCursorVariant("default"); + + return ( +
+ {renderWords()} +
+ ); +}; diff --git a/src/pages/Home.jsx b/src/pages/Home.jsx index f9f6ad3..05bd4d3 100644 --- a/src/pages/Home.jsx +++ b/src/pages/Home.jsx @@ -1,8 +1,29 @@ +import { TypewriterEffect } from "@/components/typewriter-effect"; import { projects } from "@/data/projects"; import { FaStar } from "react-icons/fa"; import { Link } from "react-router-dom"; +import { motion } from "framer-motion"; function Home({ setCursorVariant }) { + const words = [ + { + text: "Discover", + }, + { + text: "Awesome", + }, + { + text: "React", + }, + { + text: "js", + }, + { + text: "Projects", + className: "primary text-primary dark:text-primary font-bold", + }, + ]; + const renderProjectLinks = () => { return projects.map((item) => (
-
-
-
+ {["1", "2", "3"].map((item) => ( + + ))}

Hello world

-

- Discover Awesome React.js{" "} - setCursorVariant("bigText")} - onMouseLeave={() => setCursorVariant("default")} - className="relative inline-flex justify-center whitespace-nowrap font-bold text-primary" - > - Projects - -

+

Explore a curated collection of open-source projects, components, React hooks, and more, all in one place.