mirror of
https://github.com/vercel/commerce.git
synced 2025-07-05 20:51:21 +00:00
✨ feat: ModalCommon
:%s
This commit is contained in:
parent
f612256f8c
commit
c27fbef46b
24
pages/test.tsx
Normal file
24
pages/test.tsx
Normal file
@ -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 (
|
||||
<>
|
||||
<ButtonCommon onClick={onOpen}>open</ButtonCommon>
|
||||
<ModalCommon visible={visible} onClose={onClose} >
|
||||
<div className="p-10">
|
||||
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?
|
||||
</div>
|
||||
</ModalCommon>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
Test.Layout = Layout
|
24
src/components/common/ModalCommon/ModalCommon.module.scss
Normal file
24
src/components/common/ModalCommon/ModalCommon.module.scss
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
40
src/components/common/ModalCommon/ModalCommon.tsx
Normal file
40
src/components/common/ModalCommon/ModalCommon.tsx
Normal file
@ -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<HTMLDivElement>(null)
|
||||
const clickOutSide = () => {
|
||||
onClose && onClose()
|
||||
}
|
||||
useOnClickOutside(modalRef, clickOutSide)
|
||||
return (
|
||||
<>
|
||||
{visible && (
|
||||
<div
|
||||
className={s.background}
|
||||
>
|
||||
<div className={s.warpper}>
|
||||
<div
|
||||
className={s.modal}
|
||||
ref={modalRef}
|
||||
>
|
||||
<div className={s.close} onClick={clickOutSide}>
|
||||
<Close/>
|
||||
</div>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default ModalCommon
|
@ -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'
|
||||
|
22
src/components/icons/Close.tsx
Normal file
22
src/components/icons/Close.tsx
Normal file
@ -0,0 +1,22 @@
|
||||
import React from 'react'
|
||||
|
||||
interface Props {}
|
||||
|
||||
const Close = (props: Props) => {
|
||||
return (
|
||||
<svg
|
||||
width="18"
|
||||
height="18"
|
||||
viewBox="0 0 18 18"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M10.4099 9.00019L16.7099 2.71019C16.8982 2.52188 17.004 2.26649 17.004 2.00019C17.004 1.73388 16.8982 1.47849 16.7099 1.29019C16.5216 1.10188 16.2662 0.996094 15.9999 0.996094C15.7336 0.996094 15.4782 1.10188 15.2899 1.29019L8.99994 7.59019L2.70994 1.29019C2.52164 1.10188 2.26624 0.996094 1.99994 0.996094C1.73364 0.996094 1.47824 1.10188 1.28994 1.29019C1.10164 1.47849 0.995847 1.73388 0.995847 2.00019C0.995847 2.26649 1.10164 2.52188 1.28994 2.71019L7.58994 9.00019L1.28994 15.2902C1.19621 15.3831 1.12182 15.4937 1.07105 15.6156C1.02028 15.7375 0.994141 15.8682 0.994141 16.0002C0.994141 16.1322 1.02028 16.2629 1.07105 16.3848C1.12182 16.5066 1.19621 16.6172 1.28994 16.7102C1.3829 16.8039 1.4935 16.8783 1.61536 16.9291C1.73722 16.9798 1.86793 17.006 1.99994 17.006C2.13195 17.006 2.26266 16.9798 2.38452 16.9291C2.50638 16.8783 2.61698 16.8039 2.70994 16.7102L8.99994 10.4102L15.2899 16.7102C15.3829 16.8039 15.4935 16.8783 15.6154 16.9291C15.7372 16.9798 15.8679 17.006 15.9999 17.006C16.132 17.006 16.2627 16.9798 16.3845 16.9291C16.5064 16.8783 16.617 16.8039 16.7099 16.7102C16.8037 16.6172 16.8781 16.5066 16.9288 16.3848C16.9796 16.2629 17.0057 16.1322 17.0057 16.0002C17.0057 15.8682 16.9796 15.7375 16.9288 15.6156C16.8781 15.4937 16.8037 15.3831 16.7099 15.2902L10.4099 9.00019Z"
|
||||
fill="#141414"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export default Close
|
@ -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'
|
||||
|
@ -19,3 +19,5 @@ export interface RecipeProps {
|
||||
description:string
|
||||
imageSrc: string
|
||||
}
|
||||
|
||||
export type MouseAndTouchEvent = MouseEvent | TouchEvent
|
30
src/utils/useClickOutSide.ts
Normal file
30
src/utils/useClickOutSide.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import { RefObject, useEffect } from 'react'
|
||||
import { MouseAndTouchEvent } from './types.utils'
|
||||
|
||||
export function useOnClickOutside<T extends HTMLElement = HTMLElement>(
|
||||
ref: RefObject<T>,
|
||||
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])
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user