Animated modal using react, framer-motion & styled-components - GeeksforGeeks

12 Mar, 2021
In this article, we are going to learn how to create an animated modal using react, framer-motion & styled-components.
Prerequisites:
Knowledge of JavaScript (ES6).Arrow function (ES6)Ternary operatordocument.body.styleKnowledge of HTML/CSS.Basic knowledge of ReactJS.React useState
Knowledge of JavaScript (ES6).Arrow function (ES6)Ternary operatordocument.body.style
Arrow function (ES6)
Ternary operator
document.body.style
Knowledge of HTML/CSS.
Basic knowledge of ReactJS.React useState
React useState
Framer-motion: The components and attributes we are going to make use of in this tutorial.
https://www.framer.com/api/motion/component/https://www.framer.com/api/motion/animate-presence/
https://www.framer.com/api/motion/component/
https://www.framer.com/api/motion/animate-presence/
Creating React Application And Installing Module :
Step 1: Now, you will start a new project using create-react-app so open your terminal and type.
npx create-react-app toggle-modal
Step 2: After creating your project folder i.e. toggle-modal, move to it using the following command.
cd toggle-modal
Step 3: Add the npm packages you will need during the project.
npm install framer-motion styled-components
//For yarn
yarn add framer-motion styled-components
Step 5: Now open your newly created project with your favorite code editor, I am using Visual Studio Code and will recommend you to use the same.
Open the src folder and delete the following files:
logo.svgserviceWorker.jssetupTests.jsindex.cssApp.test.js (if any)
logo.svg
serviceWorker.js
setupTests.js
index.css
App.test.js (if any)
Create a file named Styles.js.
Project structure: Your folder structure tree should look like this.
Project structure
Approach:
We are going to create a Modal component with ‘showModal’ prop only to manage its state of visibility and animated using framer-motion AnimatePresence.
AnimatePresence allows components to animate out when they’re removed from the React tree and to enable exit animations.
To give spring animation to modal container we will use framer-motion spring animation with stiffness = 300.
Content of modal is geeksforgeeks image which is also animated using framer-motion motion.div.
React useState hook to manage the state of ‘showModal’ i.e. responsible to toggle the modal container.
‘displayModal’ utility function to set the ‘showModal’ value opposite of its last value to toggle modal.
Event listener for document body so that on clicking outside or on the modal, ‘showModal’ is set to false and in turn modal is disappeared.
ToggleBtn is also animated using framer-motion motion.button.
Example:
Styles.js
import styled from "styled-components";import { motion } from "framer-motion";  export const ModalBox = styled(motion.div)`  position: relative;  z-index: 2;  width: 400px;  height: 200px;  display: flex;  justify-content: center;  align-items: center;  background: #fff;`;  export const ModalContent = styled(motion.div)`  padding: 5px;`;  export const ModalContainer = styled.div`  height: 100vh;  background: #111;  display: flex;  flex-direction: column;  align-items: center;`;  export const ToggleBtn = styled(motion.button)`  cursor: pointer;  font-size: 20px;  color: #fff;  padding: 0.5rem 0.8rem;  margin-top: 3rem;  background: #3bb75e;  text-decoration: none;  border: none;  border-radius: 50px;`;
App.js
import React, { useState } from "react";import { AnimatePresence } from "framer-motion";import { ToggleBtn, ModalBox, ModalContent, ModalContainer } from "./Styles";import "./App.css";  // Modal component with 'showModal' prop only// to manage its state of visibility and// animated using framer-motionconst Modal = ({ showModal }) => {  return (    <ModalContainer>      <AnimatePresence>        {showModal && (          <ModalBox            initial={{ opacity: 0,                        y: 60, scale: 0.5 }}            animate={{              opacity: 1,              y: 0,              scale: 1,              // making use of framer-motion spring animation              // with stiffness = 300              transition: { type: "spring",                             stiffness: 300 }            }}            exit={{ opacity: 0, scale: 0.5,                     transition: { duration: 0.6 } }}>            <ModalContent              initial={{ y: -30, opacity: 0 }}              animate={{ y: 0, opacity: 1,                          transition: { delay: 0.5 } }}>              {/* Modal content is geeksforgeeks image */}              <img                src="Modal image link"                alt="geeksforgeeks"              />            </ModalContent>          </ModalBox>        )}      </AnimatePresence>    </ModalContainer>  );};  const App = () => {  // React useState hook to manage the state of 'showModal'  // i.e. responsible to toggle the modal container  const [showModal, setShowModal] = useState(false);    // utility function to set the showModal value  // opposite of its last value  // to toggle modal  const displayModal = () => {    setShowModal(!showModal);    document.getElementById("btn").style.visibility = "hidden";  };    // event listener for document body  // so that on clicking outside the modal,  // 'showModal' is set to false.  document.body.addEventListener("click", () => {    if (showModal) {      setShowModal(false);    }  });    return (    <ModalContainer>      <ToggleBtn        id="btn"        initial={{ x: -700 }}        animate={{          x: 0,          transition: { duration: 0.1 }        }}        // event listener for the toggle button        // to display modal on click        onClick={displayModal}>        Toggle Modal      </ToggleBtn>      {/* passing 'showModal' as a prop to Modal component */}      <Modal showModal={showModal} />    </ModalContainer>  );};  export default App;
index.js
import React from "react";import ReactDOM from "react-dom";import App from "./App";  ReactDOM.render(  <React.StrictMode>    <App />  </React.StrictMode>,  document.getElementById("root"));
App.css
* {  margin: 0;  box-sizing: border-box;}  img {  padding: 5px;  width: 400px;  overflow: hidden;}
Step to Run Application: Run the application using the following command from the root directory of the project.
npm start
Output: Now open your browser and go to http://localhost:3000/, you will see the following output.
Framer-motion
React-Questions
Styled-components
ReactJS
Web Technologies
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
ReactJS useNavigate() Hook
How to set background images in ReactJS ?
Axios in React: A Guide for Beginners
How to create a table in ReactJS ?
How to navigate on path by button click in react router ?
Remove elements from a JavaScript Array
Installation of Node.js on Linux
Convert a string to an integer in JavaScript
Top 10 Projects For Beginners To Practice HTML and CSS Skills
Difference between var, let and const keywords in JavaScript