skip to Main Content

App.jsx

import React, { useState } from "react";
import Modal from "./components/Modal/Modal";
export default function App() {
  const [showModal, setShowModal] = useState(false);
  return (
    <div className="app">
      <p className="ppp">Sample text</p>
      <div className="modal_menu_wrap">
        <div className="modal_menu">
          <button
            onClick={() => {
              setShowModal(true);
            }}
            className="open-btn"
          >
            Open/Close
          </button>
          <Modal active={showModal} setShowModal={setShowModal} />
        </div>
      </div>
    </div>
  );
}

index.css

.open-btn {
  padding: 10px 15px;
  border: none;
  background-color: black;
  color: aliceblue;
  cursor: pointer;
}
.open-btn:hover {
  scale: 1.05;
}
.modal_menu_wrap {
  display: flex;
  justify-content: center;
  border: 1px solid rgb(255, 0, 0) !important;
}
.modal_menu {
  width: 100%;
  max-width: 200px;
  border: 1px solid rgb(255, 0, 0) !important;
}

Modal.jsx

import styles from "./modal.module.css";
import React, { useEffect, useState } from "react";
export default function Modal({ active, setShowModal }) {
  const [showContent, setShowContent] = useState(false);
  const closeModal = () => {
    setShowContent(false);
    setTimeout(() => {
      setShowModal(false);
    }, 500);
  };
  useEffect(() => {
    if (active) {
      setShowContent(true);
    }
  }, [active]);
  if (!active) return null;
  return (
    <div
      className={
        showContent ? `${styles.modal} ${styles.showModal}` : `${styles.modal}`
      }
    >
      <p className="ppp"></p>
      <div onClick={closeModal} className={styles.closeBtn}>
        <span>&times;</span>
      </div>
    </div>
  );
}

modal.module.css

.modal {
  position: absolute;
  width: 100%;
  max-width: 200px;
  height: 300px;
  background-color: azure;
  border-radius: 10px;
  z-index: 2;
  opacity: 0.5;
  border: 1px solid rgb(255, 0, 0) !important;
  transform: translateY(-100vh);
  transition: all 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}
.showModal {
  opacity: 1;
  transform: translateY(0);
  z-index: 2;
}
.closeBtn {
  position: absolute;
  top: 10px;
  right: 20px;
  cursor: pointer;
  z-index: 9;
  border: 1px solid rgb(255, 0, 0) !important;
}
.closeBtn span {
  display: block;
  font-size: 2rem;
  font-weight: bold;
  transition: transform 0.2s ease;
}
.closeBtn span:hover {
  transform: scale(1.2);
}

It is necessary that the element appears and disappears when you click on the Open / Close button, as well as if you click outside the element field. I gave the button a value onClick={() => {setShowModal( !showModal);}}, but in this case, the animation disappears. It is necessary that the element completely disappears from the dom. There should not be a button with a cross.
Demo – https://codesandbox.io/s/serverless-dust-8vj86d?file=/src/index.css

2

Answers


  1. A better method is to add the animation to a class.

    Then set the component’s styling to the state in the last frame of the animation. And as simple as that when you add the className to the component the animations happen and return to the last state by removing the className at the end of the animation. so you may edit

     <button
                onClick={() => {
                  {/* add the className for the open stat of the componant here  */}
                  setShowModal(true);
                }}
                className="open-btn"
              >
                Open/Close
              </button>
    
    
    Login or Signup to reply.
  2. Simply edited 2 files

    First

    made the open/close button to toggle the state by setting the new value to the inverse of the old value !showModal
    in the file ` App.js`

              <button
                onClick={() => {
                  setShowModal(!showModal);
                }}
                className="open-btn"
              >
                Open/Close
              </button>
    

    Then

    I removed the line if (!active) return null;
    which is a bad approach using react! no offense but this might affect your application performance.
    And added after that a check if it is active so it removes the class

    active && showContent
    which means if active is == true then do the code on the right side of the operator
    in the file Modal.jsx

        <div
          className={
            active && showContent
              ? `${styles.modal} ${styles.showModal}`
              : `${styles.modal}`
          }
        >
    

    the final code would be :

    App.jsx

    import React, { useState } from "react";
    import Modal from "./components/Modal/Modal";
    
    export default function App() {
      const [showModal, setShowModal] = useState(false);
      return (
        <div className="app">
          <p className="ppp">Sample text</p>
    
          <div className="modal_menu_wrap">
            <div className="modal_menu">
              <button
                onClick={() => {
                  setShowModal(!showModal);
                }}
                className="open-btn"
              >
                Open/Close
              </button>
    
              <Modal active={showModal} setShowModal={setShowModal} />
            </div>
          </div>
        </div>
      );
    }
    
    

    Modal.jsx

    import styles from "./modal.module.css";
    import React, { useEffect, useState } from "react";
    export default function Modal({ active, setShowModal }) {
      const [showContent, setShowContent] = useState(false);
      const closeModal = () => {
        setShowContent(false);
        setTimeout(() => {
          setShowModal(false);
        }, 500);
      };
    
      useEffect(() => {
        if (active) {
          setShowContent(true);
        }
      }, [active]);
    
      return (
        <div
          className={
            active && showContent
              ? `${styles.modal} ${styles.showModal}`
              : `${styles.modal}`
          }
        >
          <p className="ppp"></p>
    
          <div onClick={closeModal} className={styles.closeBtn}>
            <span>&times;</span>
          </div>
        </div>
      );
    }
    
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search