Skip to content

Instantly share code, notes, and snippets.

@viclafouch
Last active January 23, 2023 21:14
Show Gist options
  • Star 21 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save viclafouch/6ee36b2cb7d28484d20f05e68b3433f9 to your computer and use it in GitHub Desktop.
Save viclafouch/6ee36b2cb7d28484d20f05e68b3433f9 to your computer and use it in GitHub Desktop.
An implementation of a Modal Component with React Hooks ! See https://react-modal.viclafouch.vercel.app
import React, { useEffect, useImperativeHandle, useState, forwardRef, useCallback } from 'react'
import { createPortal } from 'react-dom'
import './styles.css'
const modalElement = document.getElementById('modal-root')
export function Modal({ children, fade = false, defaultOpened = false }, ref) {
const [isOpen, setIsOpen] = useState(defaultOpened)
const close = useCallback(() => setIsOpen(false), [])
useImperativeHandle(ref, () => ({
open: () => setIsOpen(true),
close
}), [close])
const handleEscape = useCallback(event => {
if (event.keyCode === 27) close()
}, [close])
useEffect(() => {
if (isOpen) document.addEventListener('keydown', handleEscape, false)
return () => {
document.removeEventListener('keydown', handleEscape, false)
}
}, [handleEscape, isOpen])
return createPortal(
isOpen ? (
<div className={`modal ${fade ? 'modal-fade' : ''}`}>
<div className="modal-overlay" onClick={close} />
<span role="button" className="modal-close" aria-label="close" onClick={close}>
x
</span>
<div className="modal-body">{children}</div>
</div>
) : null,
modalElement
)
}
export default forwardRef(Modal)
.modal {
position: fixed;
overflow: hidden;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: rgba(0, 0, 0, 0.65);
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
padding: 1.5em 1em;
z-index: 999999;
box-sizing: border-box;
}
.modal.modal-fade {
animation: fade-in 1s 1 linear;
animation-fill-mode: forwards;
opacity: 0;
}
.modal > .modal-overlay {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
}
.modal > .modal-close {
position: absolute;
right: 15px;
top: 10px;
color: #5e5e5e;
cursor: pointer;
font-size: 1.25em;
padding: 7px;
background: rgba(255, 255, 255, 0.749);
border: 1px solid #c3c0c0;
border-radius: 50%;
width: 42px;
height: 42px;
display: flex;
align-items: center;
justify-content: center;
z-index: 999999;
box-sizing: border-box;
display: inline-block;
text-align: center;
}
.modal > .modal-close:hover {
background: rgba(255, 255, 255, 0.989);
}
.modal > .modal-body {
z-index: 2;
position: relative;
margin: 0 auto;
background-color: #303030;
border: 1px solid rgba(255, 255, 255, 0.25);
border-radius: 3px;
overflow-x: hidden;
overflow-y: auto;
max-height: 100%;
padding: 15px 20px;
color: #c3c0c0;
}
@keyframes fade-in {
0% {
animation-timing-function: cubic-bezier(0.2242, 0.7499, 0.3142, 0.8148);
opacity: 0;
}
100% {
opacity: 1;
}
}
@opeyemidy
Copy link

🙏 Thanks!!!

@dorinvancea
Copy link

Awesome, thanks!

@dagonib
Copy link

dagonib commented Jan 23, 2023

Hi, thanks, It was very usefull for me.
But I have a question.
The parameter "fade", how change the value to true?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment