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.

Revisions

  1. @jz222 jz222 created this gist Oct 13, 2019.
    67 changes: 67 additions & 0 deletions useDialog.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,67 @@
    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])
    ];
    };
    58 changes: 58 additions & 0 deletions useDialog.module.scss
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,58 @@
    $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);
    }
    }