-
-
Save thiennguyenenv/9e1520a4d81bfc8b847796de39732314 to your computer and use it in GitHub Desktop.
A custom hook for dialogs in React
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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]) | |
| ]; | |
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| $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