The frontend of a web application has a myriad of components, each of which has its own logic and varies in difficulty depending on the needs of our project.
Today, I will talk about a component that is present in a myriad of web pages and applications.
The modal is a window within the main window, which can be opened or closed automatically. In this article, I will try to explain how to create a modal with the React library and what logic must be implemented to achieve this goal.
- Github Repo: https://github.com/slydragonn/react-modal
I will be breaking down each line of code of the component, so we can give you an overview of the code needed to create the following modal:
- React Component:
import { useState } from "react";
import "./Modal.css";
export default function Modal({ children, title }) {
const [isModalOpen, setIsModalOpen] = useState(false);
const openModal = () => setIsModalOpen(true);
const closeModal = () => setIsModalOpen(false);
return (
<div>
<button className="modal-open" onClick={openModal}>
Open Modal
</button>
{isModalOpen ? (
<div className="modal-overlay" onClick={closeModal}>
<div className="modal-content" onClick={(e) => e.stopPropagation()}>
<h2>{title}</h2>
{children}
<button className="modal-close" onClick={closeModal}>
Close Modal
</button>
</div>
</div>
) : null}
</div>
);
}
- Component Styles:
.modal-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgb(0, 0, 0, 0.3);
display: flex;
justify-content: center;
align-items: center;
animation-name: setoverlay;
animation-duration: 0.2s;
}
.modal-content {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
gap: 10px;
background-color: rgb(0, 0, 0, 0.5);
backdrop-filter: blur(5px) saturate(200%);
padding: 20px 20px 80px 20px;
border-radius: 8px;
width: 500px;
max-width: 100%;
position: relative;
color: white;
animation-name: showmodal;
animation-duration: 0.7s;
}
.modal-open {
border-radius: 8px;
border: 1px solid transparent;
padding: 0.6em 1.2em;
font-size: 1em;
font-weight: 500;
font-family: inherit;
background-color: #1a1a1a;
cursor: pointer;
transition: border-color 0.3s;
}
.modal-open:hover {
border-color: #117554;
}
.modal-close {
position: absolute;
bottom: 10px;
right: 10px;
border-radius: 8px;
border: 1px solid transparent;
padding: 0.6em 1.2em;
font-size: 1em;
font-weight: 500;
font-family: inherit;
background: none;
cursor: pointer;
transition: color 0.3s;
}
.modal-close:hover {
color: red;
}
@keyframes setoverlay {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes showmodal {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
- Component Usage:
<Modal title="Sign up account">
<p>Enter your personal data to create your account</p>
<label htmlFor="email">Email</label>
<input id="email" placeholder="Enter your email" />
<label htmlFor="password">Password</label>
<input
id="password"
type="password"
placeholder="Enter your password"
/>
<button id="submit">Sign up</button>
</Modal>
State
The modal has a simple logic, it will be displayed when the state is true and will be hidden when it is false. To change the state, the openModal and closeModal methods are used. And to show or not the content of the modal, a conditional rendering using the ternary operator (condition ? option1 : option2)
const [isModalOpen, setIsModalOpen] = useState(false);
const openModal = () => setIsModalOpen(true);
const closeModal = () => setIsModalOpen(false);
{isModalOpen ? (
<div className="modal-overlay" onClick={closeModal}>
<div className="modal-content" onClick={(e) => e.stopPropagation()}>
<h2>{title}</h2>
{children}
<button className="modal-close" onClick={closeModal}>
Close Modal
</button>
</div>
</div>
) : null}
Glassmorphism
To achieve this translucent glass effect is quite simple, you just have to play with the background and backdrop-filter properties. The key is in the blur() filter, which is what generates the effect we want.
.modal-content {
// other properties
background-color: rgb(0, 0, 0, 0.5);
backdrop-filter: blur(5px) saturate(200%);
// more properties
}
Animations
And we cannot forget the user experience, and this can be substantially improved thanks to CSS animations. In this specific case, our animation makes the modal appear gradually thanks to the opacity property and appears from below thanks to translateY:
@keyframes showmodal {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
Children
The modal has two props: children and title. The one we are interested in is the children, since with it we can reuse the modal component for any type of content, be it a form, an alert or a card. This depends entirely on your imagination and the specific need, which in this case would be a sign up form.
export default function Modal({ children, title })
<Modal title="Sign up account">
<p>Enter your personal data to create your account</p>
<label htmlFor="email">Email</label>
<input id="email" placeholder="Enter your email" />
<label htmlFor="password">Password</label>
<input
id="password"
type="password"
placeholder="Enter your password"
/>
<button id="submit">Sign up</button>
</Modal>
With this we have all this we get a fully functional modal component with an eye-catching appearance for the user.
I hope it has been useful, until next time 👋