๐๐ป Modal UI ์ปดํฌ๋ํธ
๋ ๊ธฐ์กด์ ๋ธ๋ผ์ฐ์ ํ์ด์ง ์์ ์๋ก์ด ์๋์ฐ ์ฐฝ์ด ์๋, ๋ ์ด์ด๋ฅผ ๊น๋ ๊ฒ์ ๋งํ๋ค. ์ด๋ฒ์๋ ์ค์ ๋ก Modal Component
๋ฅผ ๊ตฌํํด๋ณด์๋ค. ๋ค์ ์ ๋ฆฌํ๋ฉฐ ์์ ํ ๋ด๊ฒ์ผ๋ก ๋ง๋ค๋ ค๊ณ ํ๋ค.
โ๏ธ OPEN Modal ๋ฒํผ์ ๋๋ฅด๋ฉด ๋ชจ๋ฌ์ฐฝ ๋จ๊ฒ ํ๊ธฐ
โ๏ธ ๋ชจ๋ฌ์ฐฝ์ X ๋ฒํผ ๋๋ฅด๋ฉด ์ฐฝ ๋ซ๊ธฐ
โ๏ธ ๋ชจ๋ฌ ํฐ์์ฐฝ์ ๋๋ฅด๋ฉด ์ฐฝ ๋ซํ์ง ์๊ฒ ํ๊ธฐ
โ๏ธ ๋ชจ๋ฌ์ฐฝ ์ธ ์๋ฌด๊ณณ์ด๋ ๋๋ฅด๋ฉด ์ฐฝ ๋ซ๊ธฐ
๐
z-index: 1;
: ์์น ์ง์ ์์์, ๊ทธ ์์ ๋๋ ํ์ ํ๋ ์ค ์์ดํ ์ Z์ถ ์์๋ฅผ ์ง์ ํ๋ค. ๋ ํฐ z-index ๊ฐ์ ๊ฐ์ง ์์๊ฐ ์์ ๊ฐ์ ์์ ์๋ฅผ ๋ฎ๋๋ค.
๐>
: ์์ ์์ ํ๊ธฐ, ex) > div.desc {}
๐onClick={(e) => e.stopPropagation()}
: event ๋ฒ๋ธ๋ง(์ด๋ฒคํธ๊ฐ ์ฐ์ํ์ฌ ๋ฐ์ํ๋ ๋ฒ๋ธ ํ์์ ์๋ฏธ)์ด๋ฒคํธ๋ฅผ ๋ง๊ธฐ ์ํ ๋ฉ์๋
โ ๋ชจ๋ฌ์ฐฝ ์ธ ๋ถ๋ถ์ ๋๋ ์๋๋ง, ์ฐฝ์ด ๋ซํ์ผํ๋๋ฐ ๋ชจ๋ฌ์ฐฝ์ ํฐ์์ฐฝ์ ๋๋ฌ๋ ์ฐฝ์ด ๋ซํ๋ ๋ฌธ์ ๊ฐ ์์๋๋ฐ ์ด ๋ฉ์๋๋ฅผ ์ฌ์ฉํด์ ํด๊ฒฐํ ์ ์์๋ค.
๐setIsOpen(!isOpen)
: !, ์ํ๊ฐ ๋ณ๊ฒฝ๋๋ ๋ฉ์๋, ex) !false -> !true -> !false -> !true
import { useState } from 'react';
import styled from 'styled-components';
export const ModalContainer = styled.div`
// Modal์ ๊ตฌํํ๋๋ฐ ์ ์ฒด์ ์ผ๋ก ํ์ํ CSS๋ฅผ ๊ตฌํ
display : flex;
justify-content : center;
align-items : center;
height : 100%;
`;
export const ModalBackdrop = styled.div`
// Modal์ด ๋ด์ ๋์ ๋ฐฐ๊ฒฝ์ ๊น์์ฃผ๋ CSS๋ฅผ ๊ตฌํ
z-index: 1; //์์น์ง์ ์์
position: fixed;
display : flex;
justify-content : center;
align-items : center;
background-color: rgba(0,0,0,0.4);
border-radius: 10px;
top : 0;
left : 0;
right : 0;
bottom : 0;
`;
export const ModalBtn = styled.button`
background-color: var(--coz-purple-600);
text-decoration: none;
border: none;
padding: 20px;
color: white;
border-radius: 30px;
cursor: grab;
`;
export const ExitBtn = styled(ModalBtn) `
background-color : #4000c7;
border-radius: 10px;
text-decoration: none;
margin: 10px;
padding: 5px 10px;
width: 40px;
height: 40px;
display : flex;
justify-content : center;
align-items : center;
`;
export const ModalView = styled.div.attrs((props) => ({
// attrs ๋ฉ์๋๋ฅผ ์ด์ฉํด์ ์๋์ ๊ฐ์ด div ์๋ฆฌ๋จผํธ์ ์์ฑ์ ์ถ๊ฐํ ์ ์๋ค.
role: 'dialog',
}))`
// Modal์ฐฝ CSS๋ฅผ ๊ตฌํํฉ๋๋ค.
display: flex;
align-items: center;
flex-direction: column;
border-radius: 20px;
width: 500px;
heigth: 200px;
background-color: #ffffff;
>div.desc {
margin: 50px;
font-size: 20px;
color: var(--coz-purple-600);
}
`;
export const Modal = () => {
const [isOpen, setIsOpen] = useState(false);
const openModalHandler = () => {
// isOpen์ ์ํ๋ฅผ ๋ณ๊ฒฝํ๋ ๋ฉ์๋๋ฅผ ๊ตฌํ
// !false -> !true -> !false
setIsOpen(!isOpen)
};
return (
<>
<ModalContainer>
<ModalBtn onClick={openModalHandler}
// ํด๋ฆญํ๋ฉด Modal์ด ์ด๋ฆฐ ์ํ(isOpen)๋ฅผ boolean ํ์
์ผ๋ก ๋ณ๊ฒฝํ๋ ๋ฉ์๋๊ฐ ์คํ๋์ด์ผ ํฉ๋๋ค.
> Open Modal
{/* ์กฐ๊ฑด๋ถ ๋ ๋๋ง์ ํ์ฉํด์ Modal์ด ์ด๋ฆฐ ์ํ(isOpen์ด true์ธ ์ํ)์ผ ๋๋ ModalBtn์ ๋ด๋ถ ํ
์คํธ๊ฐ 'Opened!' ๋ก Modal์ด ๋ซํ ์ํ(isOpen์ด false์ธ ์ํ)์ผ ๋๋ ModalBtn ์ ๋ด๋ถ ํ
์คํธ๊ฐ 'Open Modal'์ด ๋๋๋ก ๊ตฌํ */}
</ModalBtn>
{/* ์กฐ๊ฑด๋ถ ๋ ๋๋ง์ ํ์ฉํด์ Modal์ด ์ด๋ฆฐ ์ํ(isOpen์ด true์ธ ์ํ)์ผ ๋๋ง ๋ชจ๋ฌ์ฐฝ๊ณผ ๋ฐฐ๊ฒฝ์ด ๋ฐ ์ ์๊ฒ ๊ตฌํ */}
{isOpen ?
<ModalBackdrop onClick={openModalHandler}>
//event ๋ฒ๋ธ๋ง์ ๋ง๋ ๋ฉ์๋
<ModalView onClick={(e) => e.stopPropagation()}>
<ExitBtn onClick={openModalHandler}>x</ExitBtn>
<div className='desc'>HELLO FEJIGU!</div>
</ModalView>
</ModalBackdrop>
: null
}
</ModalContainer>
</>
);
};