Reputation: 119
I made a modal that given below:
export const Modal = ({ onClose, children, title = "" }) => {
const handleBackdropClick = (e) => {
e.target === e.currentTarget && onClose();
};
useEffect(() => {
document.body.style.overflow = "hidden";
return () => {
document.body.style.overflow = "unset";
};
}, []);
return (
<>
{/* Back drop */}
<div
className="fixed inset-0 flex justify-center items-top py-2 transition-opacity px-2 visible bg-slate-950 z-50 bg-opacity-50"
onClick={handleBackdropClick}
>
{/* Modal body */}
<div className="bg-white border-2 p-4 md:p-6 shadow-xl rounded-3xl w-full md:w-min overflow-y-auto min-h-fit h-max transform transition-all scale-100 opacity-100 ">
<div className="flex items-center justify-between sticky top-0 gap-8">
<h4 className="text-primary-text text-base md:text-xl font-bold w-max">
{title}
</h4>
<span className="cursor-pointer text-gray-500" onClick={onClose}>
<interfaceIcons.CloseIcon size="24" />
</span>
</div>
{children}
</div>
</div>
</>
);
};
This will be called like this :
export const HomePage= () => {
const [isModalOpen, setIsModalOpen] = useState(false);
const handleModalOpen = () => {
setIsModalOpen(!isModalOpen);
};
return (
<>
<button onClick={handleModalOpen}>Open modal</button>
{isModalOpen && (
<Modal title="My modal" onClose={handleModalOpen}>
content here!
</Modal>
)}
</>
);
};
I need a simple animation when the modal open. the problem is when we render based on condition, the animation is not affected. so how can i add the animation ?
I need a simple animation when the modal open. just like i given below
ease-in-out delay-150 duration-300
The problem is when we render based on condition, the animation is not affected. I need this kind of animation.
Upvotes: -1
Views: 508
Reputation: 2324
You can animate the modal visibility by adding the keyframes and animation in the tailwind.config.js file and using it in the modal, As shown below
tailwind.config.js file
theme: {
extend: {
keyframes: {
"fade-in": {
"0%": { opacity: 0 },
"100%": { opacity: 1 },
},
"fade-out": {
"0%": { opacity: 1 },
"100%": { opacity: 0 },
},
},
animation: {
"fade-in": "fade-in 300ms ease-in-out",
"fade-out": "fade-out 300ms ease-in-out",
},
},
}
We need to render the component only if the condition is true as it will affect the performance and Use the mentioned keyframes and animation in tailwind.config.js here in modal on the condition base
In Modal file
export const Modal = ({ onClose, children, title = "" }) => {
const [IsAnimating, setIsAnimating] = useState(false);
const handleBackdropClick = (e) => {
setIsAnimating(true);
setTimeout(() => {
onClose();
setIsAnimating(false);
}, 250);
};
useEffect(() => {
document.body.style.overflow = "hidden";
return () => {
document.body.style.overflow = "unset";
};
}, []);
return (
<>
{/* Back drop */}
<div
className={`fixed inset-0 flex justify-center items-top py-2 transition-opacity px-2 visible bg-slate-950 z-50 bg-opacity-50 ${
IsAnimating ? "animate-fade-out" : "animate-fade-in"
}`}
onClick={handleBackdropClick}
>
{/* Modal body */}
<div className="bg-white border-2 p-4 md:p-6 shadow-xl rounded-3xl w-full md:w-min overflow-y-auto min-h-fit h-max transform transition-all scale-100 opacity-100 ">
<div className="flex items-center justify-between sticky top-0 gap-8">
<h4 className="text-primary-text text-base md:text-xl font-bold w-max">
{title}
</h4>
<span
className="cursor-pointer text-gray-500"
onClick={handleBackdropClick}
>
<interfaceIcons.CloseIcon size="24" />
</span>
</div>
{children}
</div>
</div>
</>
)};
Upvotes: 0
Reputation: 3223
You can't animate it if you are adding and removing the component conditionally.
// animation effect will not work this way
{isModalOpen && (
<Modal title="My modal" onClose={handleModalOpen}>
content here!
</Modal>
)}
Alternatively, to show the transition, you can make the modal always shown in the DOM, but fake hidden style with opacity-0
and z-[-9999]
, then conditionally add and remove these classes with the help of isModalOpen
.
import { useEffect, useState } from 'react';
export const Modal = ({
onClose,
children,
title = '',
isModalOpen,
}) => {
const handleBackdropClick = (e: any) => {
e.target === e.currentTarget && onClose();
};
useEffect(() => {
document.body.style.overflow = 'hidden';
return () => {
document.body.style.overflow = 'unset';
};
}, []);
return (
<>
{/* Back drop */}
<div
className={`fixed inset-0 flex justify-center items-top py-2 transition-opacity px-2 visible z-50 bg-opacity-50 ${
!isModalOpen && 'opacity-0 z-[-9999]'
}`}
onClick={handleBackdropClick}
>
{/* Modal body */}
<div className="bg-white border-2 p-4 md:p-6 shadow-xl rounded-3xl w-full md:w-min overflow-y-auto min-h-fit h-max transform transition-all scale-100 opacity-100 ">
<div className="flex items-center justify-between sticky top-0 gap-8">
<h4 className="text-primary-text text-base md:text-xl font-bold w-max">
{title}
</h4>
<span className="cursor-pointer text-gray-500" onClick={onClose}>
close
</span>
</div>
{children}
</div>
</div>
</>
);
}
// notice I also passed "isModalOpen" to control show/hide
<Modal title="My modal" isModalOpen={isModalOpen} onClose={handleModalOpen}>
content here!
</Modal>
Here is a working snippet on Stackblitz
Upvotes: 0