brief-07-front/src/components/ui/flip-words.tsx
Mathis 74ec86c684 feat: Add multiple UI components to the codebase
This commit includes several User Interface components such as Button, DropdownMenu, FlipWords, HeroParallax, Input, Label, NavigationMenu and ToastBox. Each component was developed individually and has different attributes and behaviors. This will significantly improve the user experience and interactivity of the application.
2024-06-06 14:03:45 +02:00

85 lines
1.8 KiB
TypeScript

"use client";
import React, { useCallback, useEffect, useRef, useState } from "react";
import { AnimatePresence, motion, LayoutGroup } from "framer-motion";
import { cn } from "@/lib/utils";
export const FlipWords = ({
words,
duration = 3000,
className,
}: {
words: string[];
duration?: number;
className?: string;
}) => {
const [currentWord, setCurrentWord] = useState(words[0]);
const [isAnimating, setIsAnimating] = useState<boolean>(false);
const startAnimation = useCallback(() => {
const word = words[words.indexOf(currentWord) + 1] || words[0];
setCurrentWord(word);
setIsAnimating(true);
}, [currentWord, words]);
useEffect(() => {
if (!isAnimating)
setTimeout(() => {
startAnimation();
}, duration);
}, [isAnimating, duration, startAnimation]);
return (
<AnimatePresence
onExitComplete={() => {
setIsAnimating(false);
}}
>
<motion.div
initial={{
opacity: 0,
y: 10,
}}
animate={{
opacity: 1,
y: 0,
}}
transition={{
duration: 0.4,
ease: "easeInOut",
type: "spring",
stiffness: 100,
damping: 10,
}}
exit={{
opacity: 0,
y: -40,
x: 40,
filter: "blur(8px)",
scale: 2,
position: "absolute",
}}
className={cn(
"z-10 inline-block relative text-left text-neutral-900 dark:text-neutral-100 px-2",
className
)}
key={currentWord}
>
{currentWord.split("").map((letter, index) => (
<motion.span
key={currentWord + index}
initial={{ opacity: 0, y: 10, filter: "blur(8px)" }}
animate={{ opacity: 1, y: 0, filter: "blur(0px)" }}
transition={{
delay: index * 0.08,
duration: 0.4,
}}
className="inline-block"
>
{letter}
</motion.span>
))}
</motion.div>
</AnimatePresence>
);
};