I created a button component with text animation, but I'm encountering an issue.
When I hover over the button, the animation works smoothly. However, if I quickly move my cursor away or unhover in the middle of the animation, the text disappears unexpectedly.
https://i.sstatic.net/wz8XH.gif
This is the structure of my component:
index.tsx
import { motion } from "framer-motion";
import styles from "./styles.module.scss";
interface ButtonProps {
isActive: boolean;
toggleMenu: () => void;
}
const Button: React.FC<ButtonProps> = ({ isActive, toggleMenu }) => {
return (
<div className={styles.button}>
<motion.div
className={styles.slider}
animate={{ top: isActive ? "-100%" : "0%" }}
transition={{ duration: 0.5, type: "tween", ease: [0.76, 0, 0.24, 1] }}
>
<div className={styles.el} onClick={toggleMenu}>
<PerspectiveText label="Menu" />
</div>
<div className={styles.el} onClick={toggleMenu}>
<PerspectiveText label="Close" />
</div>
</motion.div>
</div>
);
};
interface PerspectiveTextProps {
label: string;
}
const PerspectiveText: React.FC<PerspectiveTextProps> = ({ label }) => {
return (
<div className={styles.perspectiveText}>
<p>{label}</p>
<p>{label}</p>
</div>
);
};
export default Button;
Below are the styles used for the animation (which depends on the .perspectiveText
class):
styles.module.scss
.button {
position: absolute;
top: 25px;
right: 25px;
width: 100px;
height: 40px;
cursor: pointer;
border-radius: 25px;
overflow: hidden;
.slider {
position: relative;
width: 100%;
height: 100%;
.el {
width: 100%;
height: 100%;
background-color: #c9fd74;
p {
margin: 0px;
}
&:nth-of-type(2) {
background-color: black;
p {
color: #c9fd74;
}
}
&:hover {
.perspectiveText {
transform: rotateX(90deg);
p {
&:nth-of-type(1) {
transform: translateY(-100%);
opacity: 0;
}
&:nth-of-type(2) {
opacity: 1;
}
}
}
}
}
}
}
.perspectiveText {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100%;
width: 100%;
transform-style: preserve-3d;
transition: transform 0.75s cubic-bezier(0.76, 0, 0.24, 1);
p {
transition: all 0.75s cubic-bezier(0.76, 0, 0.24, 1);
pointer-events: none;
margin: 0;
&:nth-of-type(2) {
position: absolute;
transform-origin: bottom center;
transform: rotateX(-90deg) translateY(50%);
opacity: 0;
}
}
}