[ 프로젝트 ]/빨간 망토
모달/탭 UI 구현하기
디디 ( DD )
2023. 6. 14. 23:22
(컴포넌트 구조)
마이페이지
↓ ↓
모달 탭
◆ 모달 (Modal)
// 먼저, 부모 컴포넌트인 <마이페이지>에 modal상태를 추가한다.
const [modal, setModal] = useState(false);
// 모달 창을 끌 때 필요한 (모달 컴포넌트에 내려 줄) 함수를 만든다.
const onCancel = () => {
setModal(false);
};
// 수정하기 버튼을 누르면 modal상태를 true로 바꿔준다.
// 모달 컴포넌트는 modal상태가 true인 경우에만 나타날 수 있게 한다.
return(
<>
{modal && (
<MyPageModal
onCancel={onCancel}
/>
)}
<button type="button" onClick={() => setModal(true)}>
수정하기
</button>
</>
)
// 자식 컴포넌트인 <모달>에서 앞서 내려준 함수를 받은 후,
// X 버튼을 눌렀을 때 실행되도록(모달 창이 꺼지도록) 연결한다.
export default function Modal({ onCancel }) {
return(
<div> <!-- 모달창이 되어줄 div -->
<button type="button" onClick={onCancel}>
X
</button>
</div>
)
}
(+) 모달 창의 뒤로 블러 처리를 하고 싶다면, 모달 창이 되어줄 div를 감싸는 백그라운드 div를 하나 더 만든 후, 아래와 같이 스타일을 추가해주면 된다.
// 백그라운드 div
width: 100%;
height: 100%;
position: absolute;
top: 0px;
left: 0px; // 여기까지는 배경을 전체 화면으로 맞추기 위함
background-color: rgba(0, 0, 0, 0.5);
backdrop-filter: blur(5px);
z-index: 1; // 모달 뒤 레이어에 위치시키기
// 모달 창 div
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%); // 여기까지는 모달 창 위치를 가운데로 맞추기 위함
z-index: 999; // 배경 앞 레이어에 위치시키기
◆ 탭 (Tab)
import { useState } from "react";
import styled from "styled-components";
const TabContainer = styled.div`
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: calc(4% + 3rem) 0 2rem;
> ul {
display: flex;
> li {
display: flex;
justify-content: center;
align-items: center;
height: 3rem;
width: 20rem;
color: var(--font-color-light);
font-weight: 600;
background-color: #e7d1d1;
border-radius: 40px 40px 0 0;
cursor: pointer;
&.active {
background-color: #fff;
color: var(--primary-color);
}
@media (max-width: 500px) {
height: 2.5rem;
width: 12rem;
}
}
}
`;
const TabContent = styled.div`
display: flex;
justify-content: center;
align-items: center;
height: 25rem;
width: 40rem;
background-color: #fff;
@media (max-width: 500px) {
height: 16rem;
width: 24rem;
}
`;
export default function Tab() {
const [activeTab, setActiveTab] = useState(0);
const tabs = [
{ id: 0, name: "의뢰한 심부름", content: <div>(1) 준비 중입니다.</div> },
{ id: 1, name: "수행한 심부름", content: <div>(2) 준비 중입니다.</div> },
];
return (
<TabContainer>
<ul>
{tabs.map(tab => (
<li key={tab.id} onClick={() => setActiveTab(tab.id)} className={activeTab === tab.id ? "active" : ""}>
{tab.name}
</li>
))}
</ul>
{tabs
.filter(tab => activeTab === tab.id)
.map(tab => (
<TabContent key={tab.id}>{tab.content}</TabContent>
))}
</TabContainer>
);
}
탭 컴포넌트는 길지 않아서 코드를 그대로 가져와 봤다.
로직을 설명하자면, 먼저 activeTab이라는 상태를 하나 만들어 준다. 그다음 탭 관련 정보가 담긴 tabs라는 배열을 만든다. 탭은 크게 두 부분으로 나뉘는데, 하나는 각 탭의 이름이 적힌 리스트 부분이고, 다른 하나는 각 탭의 내용이 들어가는 콘텐츠 부분이다. 리스트 부분의 이름을 클릭하면, 해당 이름을 가진 탭의 id로 activeTab 상태가 바뀌게 된다. activeTab이 되면, 즉 탭이 활성화되면, active라는 클래스가 적용되고, 흰 배경과 붉은 글씨로 리스트의 스타일이 바뀐다. 그리고 이에 맞춰 콘텐츠 부분의 내용도 활성화 상태인 탭의 내용으로 바뀐다.