Muhammed Sahad
Muhammed Sahad

Reputation: 119

How to add animation to a modal using tailwind css

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

Answers (2)

Zealous System
Zealous System

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

MHD Alaa Alhaj
MHD Alaa Alhaj

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

Related Questions