From 1f1e8a602edd901325f44a4bb60355f0843ccc27 Mon Sep 17 00:00:00 2001 From: Anoop M D Date: Tue, 4 Jan 2022 02:07:46 +0530 Subject: [PATCH] feat: modal --- .../src/components/Modal/StyledWrapper.js | 122 ++++++++++++++++++ .../src/components/Modal/index.js | 94 ++++++++++++++ .../src/components/Sidebar/index.js | 25 +++- packages/grafnode-run/src/globalStyles.js | 49 +++++++ packages/grafnode-run/src/pages/index.js | 3 + 5 files changed, 292 insertions(+), 1 deletion(-) create mode 100644 packages/grafnode-components/src/components/Modal/StyledWrapper.js create mode 100644 packages/grafnode-components/src/components/Modal/index.js create mode 100644 packages/grafnode-run/src/globalStyles.js diff --git a/packages/grafnode-components/src/components/Modal/StyledWrapper.js b/packages/grafnode-components/src/components/Modal/StyledWrapper.js new file mode 100644 index 000000000..407f6abb1 --- /dev/null +++ b/packages/grafnode-components/src/components/Modal/StyledWrapper.js @@ -0,0 +1,122 @@ +import styled from 'styled-components'; + +const Wrapper = styled.div` + &.modal--animate-out{ + animation: fade-out 0.5s forwards cubic-bezier(.19,1,.22,1); + + .grafnode-modal-card { + animation: fade-and-slide-out-from-top .50s forwards cubic-bezier(.19,1,.22,1); + } + } + + &.grafnode-modal { + position: fixed; + top: 0; + left: 0; + width: 100vw; + height: 100vh; + display: flex; + align-items: flex-start; + justify-content: center; + overflow-y: auto; + z-index: 1003; + } + + .grafnode-modal-card { + animation-duration: .85s; + animation-delay: .1s; + background: var(--color-background-top); + border-radius: var(--border-radius); + position: relative; + z-index: 1003; + max-width: calc(100% - var(--spacing-base-unit)); + box-shadow: var(--box-shadow-base); + display: flex; + flex-direction: column; + will-change: opacity,transform; + flex-grow: 0; + margin: 3vh 10vw; + margin-top: 50px; + + &.modal-sm { + min-width: 300px; + } + + &.modal-md { + min-width: 500px; + } + + &.modal-lg { + min-width: 800px; + } + + &.modal-xl { + min-width: 1140px; + } + + animation: fade-and-slide-in-from-top .50s forwards cubic-bezier(.19,1,.22,1); + } + + .grafnode-modal-header { + display: flex; + justify-content: space-between; + align-items: center; + text-transform: uppercase; + color: rgb(86 86 86); + background-color: #f1f1f1; + font-size: 0.75rem; + padding: 12px; + font-weight: 600; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + + .close { + font-size: 1.3rem; + line-height: 1; + color: #000; + text-shadow: 0 1px 0 #fff; + opacity: 0.5; + margin-top: -2px; + + &:hover { + opacity: 0.8; + } + } + } + + .grafnode-modal-content { + flex-grow: 1; + background-color: #fff; + } + + .grafnode-modal-backdrop { + height: 100%; + width: 100%; + left: 0; + top: 0; + position: fixed; + will-change: opacity; + background: transparent; + + &:before{ + content: ""; + height: 100%; + width: 100%; + left: 0; + opacity: .4; + top: 0; + background: black; + position: fixed; + } + + animation: fade-in .1s forwards cubic-bezier(.19,1,.22,1); + } + + .grafnode-modal-footer { + background-color: white; + border-bottom-left-radius: 3px; + border-bottom-right-radius: 3px; + } +`; + +export default Wrapper; diff --git a/packages/grafnode-components/src/components/Modal/index.js b/packages/grafnode-components/src/components/Modal/index.js new file mode 100644 index 000000000..8ec49898b --- /dev/null +++ b/packages/grafnode-components/src/components/Modal/index.js @@ -0,0 +1,94 @@ +import React, {useState, useEffect} from 'react'; +import StyledWrapper from './StyledWrapper'; + +const ModalHeader = ({title, handleCancel}) => ( +
+ {title ?
{title}
: null} + {handleCancel ? ( +
handleCancel() : null}> + × +
+ ) : null} +
+); + +const ModalContent = ({children}) => ( +
+ {children} +
+); + +const ModalFooter = ({confirmText, cancelText, handleSubmit, handleCancel, confirmDisabled}) => { + confirmText = confirmText || 'Save'; + cancelText = cancelText || 'Cancel'; + + return ( +
+ + + + + + +
+ ); +} + +const ConfirmModal = ({ + size, + title, + confirmText, + cancelText, + handleCancel, + handleConfirm, + children, + confirmDisabled +}) => { + const [isClosing, setIsClosing] = useState(false); + const escFunction = (event) => { + const escKeyCode = 27; + if (event.keyCode === escKeyCode) { + closeModal(); + } + }; + + const closeModal = () => { + setIsClosing(true); + setTimeout(() => handleCancel(), 500); + } + + useEffect(() => { + document.addEventListener('keydown', escFunction, false); + + return () => { + document.removeEventListener('keydown', escFunction, false); + } + }, []); + + let classes = 'grafnode-modal'; + if (isClosing) { + classes += ' modal--animate-out'; + } + return ( + +
+ closeModal()} /> + {children} + closeModal()} + handleSubmit={handleConfirm} + confirmDisabled={confirmDisabled} + /> +
+
closeModal()} /> + + ); +}; + +export default ConfirmModal; diff --git a/packages/grafnode-components/src/components/Sidebar/index.js b/packages/grafnode-components/src/components/Sidebar/index.js index da2ca3e0f..df4d04efe 100644 --- a/packages/grafnode-components/src/components/Sidebar/index.js +++ b/packages/grafnode-components/src/components/Sidebar/index.js @@ -1,11 +1,14 @@ -import React, { forwardRef, useRef } from 'react'; +import React, { useState, forwardRef, useRef } from 'react'; import Collections from './Collections'; +import Modal from '../Modal'; import Navbar from '../Navbar'; import Dropdown from '../Dropdown'; import { IconBox, IconSearch, IconDots } from '@tabler/icons'; import StyledWrapper from './StyledWrapper'; const Sidebar = ({collections, actions, dispatch, activeRequestTabId}) => { + const [modalOpen, setModalOpen] = useState(true); + const menuDropdownTippyRef = useRef(); const onMenuDropdownCreate = (ref) => menuDropdownTippyRef.current = ref; const MenuIcon = forwardRef((props, ref) => { @@ -16,8 +19,27 @@ const Sidebar = ({collections, actions, dispatch, activeRequestTabId}) => { ); }); + const handleCancel = () => { + setModalOpen(false); + }; + + const handleConfirm = () => { + setModalOpen(false); + }; + return ( + {modalOpen && ( + + Hello + + )} +
@@ -28,6 +50,7 @@ const Sidebar = ({collections, actions, dispatch, activeRequestTabId}) => {
{ menuDropdownTippyRef.current.hide(); + setModalOpen(true); }}> Create Collection
diff --git a/packages/grafnode-run/src/globalStyles.js b/packages/grafnode-run/src/globalStyles.js new file mode 100644 index 000000000..273713efd --- /dev/null +++ b/packages/grafnode-run/src/globalStyles.js @@ -0,0 +1,49 @@ +import { createGlobalStyle } from 'styled-components'; + +const GlobalStyle = createGlobalStyle` + @keyframes fade-in { + from { + opacity: 0; + } + to { + opacity: 1; + } + } + + @keyframes fade-out { + from { + opacity: 1; + } + to { + opacity: 0; + } + } + + @keyframes fade-and-slide-in-from-top { + from { + opacity: 0; + -webkit-transform: translateY(-30px); + transform: translateY(-30px); + } + to { + opacity: 1; + -webkit-transform: none; + transform: none; + } + } + + @keyframes fade-and-slide-out-from-top { + from { + opacity: 1; + -webkit-transform: none; + transform: none; + } + to { + opacity: 2; + -webkit-transform: translateY(-30px); + transform: translateY(-30px); + } + } +`; + +export default GlobalStyle; \ No newline at end of file diff --git a/packages/grafnode-run/src/pages/index.js b/packages/grafnode-run/src/pages/index.js index 413ef924b..bdc18b8f7 100644 --- a/packages/grafnode-run/src/pages/index.js +++ b/packages/grafnode-run/src/pages/index.js @@ -1,5 +1,6 @@ import Head from 'next/head'; import Main from 'pageComponents/Main'; +import GlobalStyle from '../globalStyles'; export default function Home() { return ( @@ -9,6 +10,8 @@ export default function Home() { + +