이 글은 Next.js, MUI, styled-component, zustand 환경에서 작성된 코드를 공유합니다.
소개
어디서든 열 수 있는 모달 컴포넌트입니다.
코드
모달 개발
src / components / InfoModal.tsx
"use client";
import styled from "styled-components";
import Modal from "@mui/material/Modal";
import Fade from "@mui/material/Fade";
import { Box, Button } from "@mui/material";
import { useModalStore } from "@/store";
const InfoModal = () => {
const {isOpen, title, content, close} = useModalStore();
return (
<>
{/* Modal 컴포넌트 */}
<Modal
open={isOpen} // 모달의 열림/닫힘 상태 제어
onClose={close} // 모달 닫기 이벤트 핸들러
closeAfterTransition // 트랜지션 종료 후 모달 제거
slotProps={{
backdrop: {
invisible: true,
},
}}
>
{/* Fade 애니메이션으로 모달 표시 */}
<Fade in={isOpen} timeout={300}>
{/* 모달 내부 내용 */}
<StyledBox>
<div>{title}</div>
<div>{content}</div>
<Button onClick={close}>닫기</Button>
</StyledBox>
</Fade>
</Modal>
</>
);
};
export default InfoModal;
// Styled Component: 모달 박스 스타일 정의
const StyledBox = styled(Box)`
position: absolute; // 박스를 화면 중앙에 위치시키기 위한 절대 위치 지정
top: 50%; // 화면 세로 중앙
left: 50%; // 화면 가로 중앙
transform: translate(-50%, -50%); // 박스 크기 고려하여 정확히 중앙에 배치
width: 200px; // 박스의 너비
background-color: white;
border: 2px solid #000; // 검은색 테두리
box-shadow: 24px 24px 24px rgba(0, 0, 0, 0.2); // 그림자 효과
padding: 16px; // 내부 여백
`;
모달이 열림 상태일 때 보여줄 컴포넌트입니다.
모달 열림 여부는 store에 정의된 state를 사용합니다.
모달 상태를 저장할 store 개발
src / store / modalStore.ts
import { ModalState } from "@/types/store/modal.type";
import { create } from "zustand";
export const useModalStore = create<ModalState>((set) => ({
isOpen: false,
title: "",
content: "",
open: ({ title, content }) => set((state) => ({ ...state, isOpen: true, title: title, content: content })),
close: () => set((state) => ({ ...state, isOpen: false })),
}));
스토어 정의에 필요한 타입 정의
src / type / store / modal.type.ts
export type ModalState = {
isOpen: boolean;
title: string | null;
content: string | null;
open: ({ title, content }: openFuncParam) => void;
close: () => void;
};
type openFuncParam = {
title: string;
content: string;
};
모달 관련 상태가 저장된 store와 store type입니다.
isOpen으로 모달 열림 여부를 판단하며 title과 content에 모달에 들어갈 내용이 담겨있습니다.
open함수로 모달 열기와 동시에 모달 내용을 설정할 수 있으며 close로 모달을 닫을 수 있습니다.
최상위 DOM에서 모달 컴포넌트 호출
src / app / layout.tsx
import type { Metadata } from "next";
import { AppRouterCacheProvider } from "@mui/material-nextjs/v15-appRouter";
import InfoModal from "@/components/common/view/InfoModal";
export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="ko">
<body>
<InfoModal/>
{children}
</body>
</html>
);
}
모달을 DOM 최상위에 위치하기 위해 layout.tsx 내부에 삽입합니다.
원하는 위치에서 모달 열고 닫기
"use client";
import { useModalStore } from "@/store";
const Home = () => {
const { open } = useModalStore();
const onClick = ()=>{
open({title:"예시 타이틀", content:"예시 내용"});
}
return (
<>
<button onClick={onClick}>모달 열기</button>
</>
);
};
export default Home;
원하는 위치에서 open 함수를 통해 모달을 열 수 있습니다.
'프론트엔드 > Component' 카테고리의 다른 글
[Component] 2단 사이드바 컴포넌트(MUI + styled-components + Zustand) (1) | 2024.12.26 |
---|---|
[Component] 사이드바 컴포넌트(MUI + styled-components + Zustand) (0) | 2024.12.26 |
[Component] 모달(팝업)창 컴포넌트 (0) | 2024.12.18 |
[Component] React + MUI + react-swipeable + styled-component를 활용한 캐러셀 구현 (0) | 2024.11.21 |
리액트 모바일 슬라이더 라이브러리 (0) | 2024.03.13 |