This is the start of a new series I’m working on where we’ll be going through common components and recreate them.
After some consideration I remember how many times I had to create an Overlay component. Because of this the decision wasn’t too difficult and decided to use this as the pilot of the series. Of course, we’ll add some extras to it to make things more interesting.
The goal is simple: Have a component that can cover the user’s screen and display extra information on it. Whether it may be an alert, prompt, image, form etc.
With that out of the way, let’s get started.
First, I’ll create a new React application using Create-React-App. To do that I’ll run this command in my terminal:
npx create-react-app medium-overlay
Now that it’s all finished, we can run our application by typing npm start in the terminal. You should see it if you visit http://localhost:3000 in your browser.
It’s time we get some coding done. First, let’s create the files for our new Overlay component. In our src folder, let’s create a new folder called components. Inside that let’s create 2 files, named Overlay.js and Overlay.css. These files will host our component and the styling.
Next, we can add to Overlay.js our simplified component:
import { Fragment } from "react";
import "./Overlay.css";
export function Overlay({ isOpen, children }) {
return (
<Fragment>
{isOpen && (
<div className="overlay">
{children}
</div>
)}
</Fragment>
);
}
export default Overlay;
A quick summary of what this component does:
- Renders a div if the passed in isOpen prop is true
- Renders whatever you pass (children) in to this component inside the parent div. This enables us to reuse this component.
Let’s update our App.js file with our new component and some more logic.
import { useState } from "react";
import Overlay from "./components/Overlay";
function App() {
const [isOpen, setIsOpen] = useState(false);
const toggleOverlay = () => {
setIsOpen(!isOpen);
};
return (
<div className="App">
<button onClick={toggleOverlay}>Open</button>
<Overlay isOpen={isOpen} onClose={toggleOverlay}>
<h1>Content in overlay</h1>
</Overlay>
</div>
);
}
export default App;
As you can see we have a new button that opens/closes that Overlay. Furthermore we use our React component state to keep track and change the status of our Overlay. And last, we have a toggleOverlay method that changes our isOpen property to it’s opposite. If it’s true, it’ll set it to false, vice-versa.
We can notice immediately that a few things are off or missing in our component once we click on the button.
- There’s no background or visibility change. Our Overlay should cover the entire screen. It also should have a clear differentiation between background and content.
- That brings us to the next problem that’s about to happen. If we take the whole screen of the user, we need to let the user close it. We don’t want to trap the user.
Now let’s get back to our Overlay component and add a closing button on the top right corner, and a background. We’ll also have to pass a method to this component that’ll close this component. For extra points, we’ll close the Overlay when the user clicks on the icon OR on the background.
import { Fragment } from "react";
import "./Overlay.css";
export function Overlay({ isOpen, onClose, children }) {
return (
<Fragment>
{isOpen && (
<div className="overlay">
<div className="overlay__background" onClick={onClose} />
<div className="overlay__container">
<div className="overlay__controls">
<button
className="overlay__close"
type="button"
onClick={onClose}
/>
</div>
{children}
</div>
</div>
)}
</Fragment>
);
}
export default Overlay;
Looking at the changes above, you’ll see 2 main additions to our component.
- A Div with overlay__background class. You guessed it right, this will be our background. It also has the event handler that we mentioned, so when a user clicks on it, it’ll close.
- Another Div with overlay__container class on it. This’ll serve as a wrapper for both our content, and our controls on the top of the Overlay.
To finish it up, only thing left to do is add some styling.
.overlay__background {
background-color: rgba(0, 0, 0, 0.5);
width: 100vw;
height: 100vh;
position: fixed;
top: 0;
left: 0;
cursor: pointer;
z-index: 9;
}
.overlay__container {
background-color: white;
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
z-index: 10;
padding: 30px;
width: fit-content;
height: fit-content;
}
.overlay__controls {
display: flex;
justify-content: flex-end;
align-items: center;
}
.overlay__close:after {
display: inline-block;
content: "\00d7";
}
.overlay__close {
border: none;
background-color: transparent;
font-size: 36px;
cursor: pointer;
}
On Line 1 you’ll see how we add the background colour and how we make the component take the full screen. Just below that you can see how the middle part of the Overlay component scales based on it’s content. And in the end you can learn about the positioning and styling of the close button that uses pure CSS.
This wraps up our first tutorial about common components, you can find the Github repo here.
If you like this article and would like to see more, please comment down below and let me know which component you’d like to see next.