Hi, I'm Marian and I just released my new side project called Cow Pilot. It's a to-do list app, but you can only add 6 tasks.
Today I wanted to share how I created a custom confirm box, since the standard ones look kinda boring and different in every browser.
For example, the same confirm box looks like this in Firefox
and like this in Chrome
Not pretty. It can be set up like this.
<button
className="delete button"
onClick={() => {
const confirmBox = window.confirm(
"Do you really want to delete this Crumb?"
)
if (confirmBox === true) {
handleDeleteCrumb(bookmark)
}
}}>
</button>
Introduction
The custom variant works like this:
- Add an opaque full screen background to the DOM
- Below that, add a
div
that acts as the confirm box container - Inside the
div
add a text and the Cancel and OK buttons
In normal state, the background and the container both have the property display: none
, which means they are not visible on the screen and other than visibility: hidden
don't take up any space.
We make them visible by clicking on a button, for example in my case "Delete Task", which calls a function that changes display: none
to display: flex
(or instead of anything else that is not none
)
There are several ways to make them visible:
- use
display.querySelector(".container").style.display =
to unhide and hide the box - use useState to add and remove a class with property
display: none
- use inline styles and toggle the
display: none
property with useState - use styled components, a library I have started using recently. We pass props to the styled component and use it to toggle between
display: flex
anddisplay: none
In this post I will focus on the first variant. If you are interested I can make a follow-up for the other ways as well, just let me know in the comments.
Creating the Elements
First, let's create the background. I'm adding it to be able to close the box by clicking anywhere outside of it. I also disable scrolling with overflow:hidden
while the background is visible. I like to make it black and 50% opaque to accentuate the confirm box, but you can also make it completely opaque.
/* The JSX */
<>
<div
className="confirm-bg"
onClick={() => handleConfirmationBox()}>
</div>
</>
/* The CSS */
.confirm-bg {
position: fixed;
display: none;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: #202020;
opacity: 0.55;
overflow: hidden; /* disable scrolling*/
z-index: 2; /* higher than all other items, but lower than
the confirm box*/
}
Next we add the container. I use position: fixed
to place it close to the delete button. In our component we have to add it right before the background, otherwise it will appear behind it on the screen.
/* The JSX */
<>
<div className="container">
<div className="confirmation-text">
Do you really want to delete this task?
</div>
<div className="button-container">
<button
className="cancel-button"
onClick={() => handleConfirmationBox()}>
Cancel
</button>
<button
className="confirmation-button"
onClick={handleDeleteTask}>
Delete
</button>
</div>
</div>
<div
className="confirm-bg">
onClick={() => handleConfirmationBox()}
</div>
</>
/* The CSS */
.container {
display: none;
flex-direction: column;
position: fixed;
background-color: #f37736;
width: 230px;
top: 75%;
left: 50%;
transform: translate(-50%, -75%);
border-radius: 0.3rem;
padding: 1rem;
z-index: 5; /* Higher than the z-index of the background */
}
.confirmation-text {
display: flex;
color: white;
margin: 0.5rem 0 2rem;
text-align: center;
line-height: 2rem;
font-size: 1.1rem;
}
.button-container {
display: flex;
margin-top: auto;
justify-content: space-between;
}
.confirmation-button, delete-button {
display: inline-flex;
background-color: #cc0000;
color: white;
padding: 0.7rem 1.4rem;
border: none;
border-radius: 0.3rem;
font-size: 1rem;
}
.cancel-button {
background-color: #999999;
}
.confirmation-button:hover {
background-color: red;
cursor: pointer;
}
.cancel-button:hover {
background-color: #b2b2b2;
cursor: pointer;
}
Toggle the elements
Now the elements are set up and we can work on showing them and hiding them again.
First we need the button that triggers the confirmation check. It can be anywhere in the component. On click, the button calls a function that changes the display
property .
/* JSX */
<button
className="delete-button"
onClick={() => {handleConfirmationBox()}>
Delete
</button>
Inside of handleConfirmationBox
we will use a state
to check, if we should show or hide the confirmation check. We use a boolean value and set the default to false. In the handleConfirmationBox function, we assign false to hiding the popup.
We call this function when we:
- click on the delete task button
- click on the cancel button
- click anywhere outside the box, while it is visible
/* define the state */
import { useState } from "react"
const [delTask, setDelTask] = useState(false)
/* if delTask is false, change the display properties of our
- two elements and change delTask to true, so that next time
- the function is called, the elements are hidden again
*/
const handleConfirmationBox = () => {
if (!delTask) {
document.querySelector(".confirm-bg").style.display = "flex"
document.querySelector(".container").style.display = "flex"
setDelTask(true)
} else {
document.querySelector(".confirm-bg").style.display = "none"
document.querySelector(".container").style.display = "none"
setDelTask(false)
}
Final words
And that's it. Now the confirmation will look the same on all devices and we can customize it the way we want. Like I say, there are several ways to achieve the hide/unhide. I personally like styled components because I can just pass the delTask
state as prop and change the display
property based on that.
If you have any questions or if I missed something, please let me know.
Top comments (1)
Nice