diff --git a/pages/test.tsx b/pages/test.tsx new file mode 100644 index 000000000..5f798909a --- /dev/null +++ b/pages/test.tsx @@ -0,0 +1,24 @@ +import { useState } from 'react' +import { ButtonCommon, Layout, ModalCommon } from 'src/components/common' + +export default function Test() { + const [visible, setVisible] = useState(false) + const onClose = () => { + setVisible(false) + } + const onOpen = () => { + setVisible(true) + } + return ( + <> + open + +
+ Lorem ipsum dolor sit amet consectetur adipisicing elit. Consectetur officiis dolorum ea incidunt. Sint, cum ullam. Labore vero quod itaque, officia magni molestias! Architecto deserunt soluta laborum commodi nesciunt delectus similique temporibus distinctio? Facere eaque minima enim modi magni, laudantium, animi mollitia beatae repudiandae maxime labore error nesciunt, nisi est? +
+
+ + ) +} + +Test.Layout = Layout diff --git a/src/components/common/ModalCommon/ModalCommon.module.scss b/src/components/common/ModalCommon/ModalCommon.module.scss new file mode 100644 index 000000000..58c7d30b3 --- /dev/null +++ b/src/components/common/ModalCommon/ModalCommon.module.scss @@ -0,0 +1,24 @@ +.background{ + @apply fixed inset-0 overflow-y-auto; + background: rgba(20, 20, 20, 0.65); + z-index: 10000; + .warpper{ + @apply flex justify-center items-center min-h-screen; + .modal{ + // @apply bg-white inline-block; + @apply inline-block align-bottom bg-white relative; + max-width: 50%; + padding: 3.2rem; + box-shadow: 0px 8px 16px rgba(0, 0, 0, 0.24); + border-radius: 1.2rem; + .close{ + @apply absolute; + &:hover{ + cursor: pointer; + } + top:4.4rem; + right: 4.4rem; + } + } + } +} \ No newline at end of file diff --git a/src/components/common/ModalCommon/ModalCommon.tsx b/src/components/common/ModalCommon/ModalCommon.tsx new file mode 100644 index 000000000..fcca8a84a --- /dev/null +++ b/src/components/common/ModalCommon/ModalCommon.tsx @@ -0,0 +1,40 @@ +import React, { useRef } from 'react' +import { Close } from 'src/components/icons' +import { useOnClickOutside } from 'src/utils/useClickOutSide' +import s from "./ModalCommon.module.scss" +interface Props { + onClose: () => void + visible: boolean + children:React.ReactNode +} + +const ModalCommon = ({ onClose, visible,children }: Props) => { + const modalRef = useRef(null) + const clickOutSide = () => { + onClose && onClose() + } + useOnClickOutside(modalRef, clickOutSide) + return ( + <> + {visible && ( +
+
+
+
+ +
+ {children} +
+
+
+ )} + + ) +} + +export default ModalCommon diff --git a/src/components/common/index.ts b/src/components/common/index.ts index 73f4f2709..7fc104020 100644 --- a/src/components/common/index.ts +++ b/src/components/common/index.ts @@ -24,3 +24,4 @@ export { default as MenuDropdown} from './MenuDropdown/MenuDropdown' export { default as NotiMessage} from './NotiMessage/NotiMessage' export { default as VideoPlayer} from './VideoPlayer/VideoPlayer' export { default as SelectCommon} from './SelectCommon/SelectCommon' +export { default as ModalCommon} from './ModalCommon/ModalCommon' diff --git a/src/components/icons/Close.tsx b/src/components/icons/Close.tsx new file mode 100644 index 000000000..090bb29f4 --- /dev/null +++ b/src/components/icons/Close.tsx @@ -0,0 +1,22 @@ +import React from 'react' + +interface Props {} + +const Close = (props: Props) => { + return ( + + + + ) +} + +export default Close diff --git a/src/components/icons/index.ts b/src/components/icons/index.ts index ae39054a8..fc7f993a9 100644 --- a/src/components/icons/index.ts +++ b/src/components/icons/index.ts @@ -9,3 +9,6 @@ export { default as IconHome } from './IconHome' export { default as IconShopping } from './IconShopping' export { default as IconHeart } from './IconHeart' export { default as IconVector } from './IconVector' +export { default as ArrowLeft } from './ArrowLeft' +export { default as ArrowRight } from './ArrowRight' +export { default as Close } from './Close' diff --git a/src/utils/types.utils.ts b/src/utils/types.utils.ts index 6c7ed8401..2c99df73a 100644 --- a/src/utils/types.utils.ts +++ b/src/utils/types.utils.ts @@ -18,4 +18,6 @@ export interface RecipeProps { title: string description:string imageSrc: string -} \ No newline at end of file +} + +export type MouseAndTouchEvent = MouseEvent | TouchEvent \ No newline at end of file diff --git a/src/utils/useClickOutSide.ts b/src/utils/useClickOutSide.ts new file mode 100644 index 000000000..d68e742fb --- /dev/null +++ b/src/utils/useClickOutSide.ts @@ -0,0 +1,30 @@ +import { RefObject, useEffect } from 'react' +import { MouseAndTouchEvent } from './types.utils' + +export function useOnClickOutside( + ref: RefObject, + callback: (event: MouseAndTouchEvent) => void +) { + useEffect(() => { + const listener = (event: MouseAndTouchEvent) => { + const el = ref?.current + + // Do nothing if clicking ref's element or descendent elements + if (!el || el.contains(event.target as Node)) { + return + } + + callback(event) + } + + document.addEventListener(`mousedown`, listener) + document.addEventListener(`touchstart`, listener) + + return () => { + document.removeEventListener(`mousedown`, listener) + document.removeEventListener(`touchstart`, listener) + } + + // Reload only if ref or handler changes + }, [ref, callback]) +}