I want to share an issue I am experiencing with my toggle menu. Every time I refresh the page, I notice that it appears and disappears intermittently. My desire is that this behavior does not occur; the toggle menu should only open when I click on the corresponding icon. Upon refreshing the page, it should not exhibit this unexpected behavior.
Project https://github.com/jolgo1989/madesWeb
https://codesandbox.io/p/github/jolgo1989/madesWeb/main
Video https://www.youtube.com/watch?v=ETGJOXd6z4M
const variants = {
open: {
clipPath: "circle(1200px at 50px 50px)",
transition: {
type: "spring",
stiffness: 20,
},
},
closed: {
clipPath: "circle(30px at 50px 50px)",
transition: {
delay: 0.5,
type: "spring",
stiffness: 400,
damping: 40,
},
},
};
const Sidebar = () => {
// Estado para controlar si el sidebar está abierto o cerrado
const [open, setOpen] = useState(false);
return (
// Componente motion.div con animación basada en el estado 'open'
<motion.div className="sidebar" animate={open ? "open" : "closed"}>
{/* Contenido del sidebar con animación de fondo */}
<motion.div className="bg" variants={variants}>
<Links />
</motion.div>
{/* Botón de alternancia para abrir/cerrar el sidebar */}
<ToggleButton setOpen={setOpen} />
</motion.div>
);
};
export default Sidebar;
function TogglrButton({ setOpen }) {
return (
<button onClick={() => setOpen((prev) => !prev)}>
<svg width="23" height="23" viewBox="0 0 23 23">
<motion.path
strokeWidth="3"
stroke="black"
strokeLinecap="round"
variants={{
closed: { d: "M 2 2.5 L 20 2.5" },
open: { d: "M 3 16.5 L 17 2.5" },
}}
/>
<motion.path
strokeWidth="3"
stroke="black"
strokeLinecap="round"
d="M 2 9.423 L 20 9.423"
variants={{
closed: { opacity: 1 },
open: { opacity: 0 },
}}
/>
<motion.path
strokeWidth="3"
stroke="black"
strokeLinecap="round"
variants={{
closed: { d: "M 2 16.346 L 20 16.346" },
open: { d: "M 3 2.5 L 17 16.346" },
}}
/>
</svg>
</button>
);
}
const variants = {
open: {
transition: {
staggerChildren: 0.1,
},
},
closed: {
transition: {
staggerChildren: 0.05,
staggereDirection: -1,
},
},
};
// Variantes de animación para el componente motion.a
const itemVariants = {
open: {
y: 0,
opacity: 1,
},
closed: {
y: 50,
opacity: 0,
},
};
const Links = () => {
const items = [
"Inicio",
"Quienes Somos",
"Noticias",
"Proyectos",
"Contactenos",
];
return (
<motion.div className="links" variants={variants}>
{items.map((item) => (
<motion.a
href={`#${item}`}
key={item}
variants={itemVariants}
//Componentes de framer-motion
whileHover={{ scale: 1.1 }}
whileTap={{ scale: 0.95 }}
>
{item}
</motion.a>
))}
</motion.div>
);
};
export default Links;
Updated:
The flash you are seeing is because there is not an initial clip-path
property set for the .bg
. This makes it so that the page has to wait for the framer motion Javascript to apply the styles defined in your variants
, which can take long enough for the you to see the flashing content. This can be fixed by applying a default clip-path
property to your .bg
class like so:
.bg {
position: fixed;
z-index: 999; //position y z-index de estar tanto en el bg como button
top: 0;
left: 0;
bottom: 0;
width: 400px;
background: white;
clip-path: circle(0px at 0px 0px);
...
}
Here is an updated working example.
-------------
Original:
Add initial={false}
to the motion.div
with the variants like so:
const Sidebar = () => {
// Estado para controlar si el sidebar está abierto o cerrado
const [open, setOpen] = useState(false);
return (
// Componente motion.div con animación basada en el estado 'open'
<motion.div className="sidebar" animate={open ? "open" : "closed"}>
{/* Contenido del sidebar con animación de fondo */}
<motion.div className="bg" initial={false} variants={variants}>
<Links />
</motion.div>
{/* Botón de alternancia para abrir/cerrar el sidebar */}
<ToggleButton setOpen={setOpen} />
</motion.div>
);
};
This will disable to mounting animation that you're seeing. You can read more about the initial
prop it in the Framer Motion docs. I've also made this working example.