Skip to content

Instantly share code, notes, and snippets.

@thiennguyenenv
Forked from jz222/useDialog.js
Created April 3, 2020 05:47
Show Gist options
  • Save thiennguyenenv/9e1520a4d81bfc8b847796de39732314 to your computer and use it in GitHub Desktop.
Save thiennguyenenv/9e1520a4d81bfc8b847796de39732314 to your computer and use it in GitHub Desktop.
A custom hook for dialogs in React
import React, { useCallback, useEffect, useRef, useState } from 'react';
import Button from 'components/UI/button/button';
import styling from './useDialog.module.scss';
export default (cb) => {
const [{ open, params }, setDialogMeta] = useState({ open: false });
const containerRef = useRef(null);
// Scales out the dialog
const _scaleOut = () => {
containerRef.current.style = 'transform: scale(0.95);';
document.body.style.cssText = 'overflow-y: auto;';
};
// Executes the callback and closes the dialog
const _confirm = () => {
_scaleOut();
setTimeout(() => {
if (params && params.push) {
cb(...params);
} else {
cb();
}
setDialogMeta(false);
}, 150);
};
// Closes the dialog without executing the callback
const _cancel = () => {
_scaleOut();
setTimeout(() => setDialogMeta(false), 150);
};
// Prevents the background from being scrolled while the dialog is open
useEffect(() => {
if (open) {
document.body.style.cssText = 'overflow-y: hidden;';
}
}, [open]);
// The dialog component that will be rendered when opened
const Dialog = ({ title, text, label }) => (
<div className={styling.backdrop}>
<div className={styling.dialog} ref={containerRef}>
<h3>{title}</h3>
<p>{text}</p>
<div>
<Button title={label} color='black' click={_confirm} />
<Button title='Cancel' color='transparent' click={_cancel} />
</div>
</div>
</div>
);
// Returns the function to open the dialog and the dialog component wrapped
// in useCallback to prevent it from being registered multiple times
return [
setDialogMeta,
useCallback(props => open ? <Dialog {...props} /> : null, [open])
];
};
$white: white;
$grey: #EFF4FC;
$radius: 4px;
$shadow: 0 10px 28px -5px rgba(15, 35, 98, .15), 0 10px 15px -10px rgba(0, 0,0 , .2), 0 -5px 15px -5px rgba(0, 0, 0, .025);
.backdrop {
position: fixed;
top: 70px;
width: 100%;
height: calc(100% - 70px);
padding-bottom: 70px;
display: flex;
justify-content: center;
align-items: center;
background-color: rgba(255, 255, 255, 0.7);
backdrop-filter: blur(5px);
overflow: auto;
animation: fadeIn 0.1s;
z-index: 100;
}
.dialog {
width: 450px;
padding: 20px;
border-radius: $radius;
border: 1px solid $grey;
background-color: $white;
box-shadow: $shadow;
animation: scaleIn 0.15s linear;
transition: transform 0.15s;
div {
display: flex;
button:first-child {
margin-right: 20px;
}
}
h3 {
margin-bottom: 15px;
}
}
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes scaleIn {
from {
transform: scale(0.95);
}
to {
transform: scale(1);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment