728x90
Modal UI 컴포넌트는 기존의 브라우저 페이지 위에 새로운 윈도우 창이 아닌, 레이어를 까는 것을 말합니다.
import { useEffect, useRef, useState } from 'react'
import styled from 'styled-components'
export const ModalContainer = styled.div`
// TODO : Modal을 구현하는데 전체적으로 필요한 CSS를 구현합니다.
display: flex;
justify-content: center;
align-items: center;
height: 100%;
position: relative;
`
export const ModalBackdrop = styled.div`
// TODO : Modal이 떴을 때의 배경을 깔아주는 CSS를 구현합니다.
position: fixed;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
background-color: rgba(0, 0, 0, 0.5);
z-index: 1;
`
export const ModalBtn = styled.button`
background-color: #4000c7;
text-decoration: none;
border: none;
padding: 20px;
color: white;
border-radius: 30px;
cursor: grab;
`
export const ModalView = styled.div.attrs(props => ({
// attrs 메소드를 이용해서 아래와 같이 div 엘리먼트에 속성을 추가할 수 있습니다.
role: 'dialog',
}))`
// TODO : Modal창 CSS를 구현합니다.
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background-color: white;
width: 200px;
height: 100px;
border-radius: 1rem;
position: relative;
> .close-btn {
position: absolute;
top: 2px;
right: 7px;
cursor: pointer;
}
`
export const Modal = () => {
const [isOpen, setIsOpen] = useState(false)
const el = useRef()
const openModalHandler = e => {
// TODO : isOpen의 상태를 변경하는 메소드를 구현합니다.
console.log(e)
setIsOpen(isOpen === true ? false : true)
}
const handleClickOutside = ({ target }) => {
if (isOpen && !el.current.contains(target)) setIsOpen(false)
}
useEffect(() => {
window.addEventListener('click', handleClickOutside)
return () => {
window.removeEventListener('click', handleClickOutside)
}
}, [])
return (
<>
<ModalContainer>
// 버튼을 클릭했을 때 openModalHandler를 클릭합니다.
<ModalBtn onClick={openModalHandler}>
// isOpen이 true가 되었을 때는 'Opened!' false일 때는 'Open Modal'
{isOpen ? 'Opened!' : 'Open Modal'}
</ModalBtn>
// isOpen이 true일 때 ModalBackdrop, ModalView를 실행합니다.
{isOpen ? (
<ModalBackdrop onClick={openModalHandler}>
<ModalView
onClick={event => {
// 상위 엘리먼트에 이벤트를 전달하는 막기 위해
event.stopPropagation()
}}
>
<div className="close-btn" onClick={openModalHandler}>
// x 마크를 보여줍니다.
×
</div>
<div>HELLO CODESTATES!</div>
</ModalView>
</ModalBackdrop>
) : null}
</ModalContainer>
</>
)
}
728x90
'스프린트 > react-custom-component' 카테고리의 다른 글
react-custom-component tag (0) | 2021.11.01 |
---|---|
React Custom Component Tag (0) | 2021.11.01 |
React Custom Component Tab (0) | 2021.11.01 |