-
Notifications
You must be signed in to change notification settings - Fork 0
Modal 컴포넌트 사용 가이드
pillow12360 edited this page Nov 25, 2024
·
1 revision
Modal 컴포넌트는 합성 컴포넌트 패턴을 사용하여 구현된 재사용 가능한 다이얼로그 컴포넌트입니다.
- 직관적인 API
- 유연한 커스터마이징
- 접근성 지원
- TypeScript 지원
import { Modal, useModal } from '@/components/Modal';
function Example() {
const [isOpen, setIsOpen] = useState(false);
return (
<>
<Button onClick={() => setIsOpen(true)}>모달 열기</Button>
<Modal isOpen={isOpen} onClose={() => setIsOpen(false)}>
<Modal.Header>
<h2>제목</h2>
<Modal.CloseButton onClick={() => setIsOpen(false)} />
</Modal.Header>
<Modal.Content>
<p>내용</p>
</Modal.Content>
<Modal.Footer>
<Button onClick={() => setIsOpen(false)}>닫기</Button>
</Modal.Footer>
</Modal>
</>
);
}
// App.tsx에 Provider 추가
function App() {
return (
<Modal.Provider>
<AppContent />
</Modal.Provider>
);
}
// 컴포넌트에서 useModal 훅 사용
function Example() {
const { openModal, closeModal } = useModal();
const handleOpenModal = () => {
openModal(
<Modal.Content>
<p>모달 내용</p>
</Modal.Content>
);
};
return <Button onClick={handleOpenModal}>모달 열기</Button>;
}
헤더 영역을 정의하는 컴포넌트
<Modal.Header>
<h2>제목</h2>
<Modal.CloseButton />
</Modal.Header>
본문 영역을 정의하는 컴포넌트
<Modal.Content>
<p>모달의 내용이 들어갑니다.</p>
</Modal.Content>
하단 영역을 정의하는 컴포넌트
<Modal.Footer>
<Button variant="ghost">취소</Button>
<Button variant="primary">확인</Button>
</Modal.Footer>
닫기 버튼 컴포넌트
<Modal.CloseButton onClick={onClose} />
Prop | Type | Required | Description |
---|---|---|---|
isOpen | boolean | Yes | 모달의 표시 여부 |
onClose | () => void | Yes | 모달 닫기 핸들러 |
className | string | No | 추가 스타일 클래스 |
Prop | Type | Required | Description |
---|---|---|---|
children | ReactNode | No | 컴포넌트 내용 |
className | string | No | 추가 스타일 클래스 |
function AlertModal() {
const [isOpen, setIsOpen] = useState(false);
return (
<Modal isOpen={isOpen} onClose={() => setIsOpen(false)}>
<Modal.Header>
<h2>알림</h2>
</Modal.Header>
<Modal.Content>
<p>처리가 완료되었습니다.</p>
</Modal.Content>
<Modal.Footer>
<Button onClick={() => setIsOpen(false)}>확인</Button>
</Modal.Footer>
</Modal>
);
}
function ConfirmModal({ isOpen, onClose, onConfirm, message }) {
return (
<Modal isOpen={isOpen} onClose={onClose}>
<Modal.Header>
<h2>확인</h2>
<Modal.CloseButton onClick={onClose} />
</Modal.Header>
<Modal.Content>
<p>{message}</p>
</Modal.Content>
<Modal.Footer>
<Button variant="ghost" onClick={onClose}>취소</Button>
<Button variant="primary" onClick={onConfirm}>확인</Button>
</Modal.Footer>
</Modal>
);
}
<Modal
isOpen={isOpen}
onClose={onClose}
className="max-w-2xl"
>
<Modal.Header className="bg-primary text-white">
<h2>커스텀 스타일 모달</h2>
</Modal.Header>
<Modal.Content className="py-8">
<p>내용</p>
</Modal.Content>
</Modal>
// ❌ 잘못된 예시
<Modal isOpen={true}>
// ✅ 좋은 예시
const [isOpen, setIsOpen] = useState(false);
<Modal isOpen={isOpen} onClose={() => setIsOpen(false)}>
// ✅ 제목에 적절한 헤딩 태그 사용
<Modal.Header>
<h2>모달 제목</h2>
</Modal.Header>
// ✅ 닫기 버튼에 적절한 레이블 제공
<Modal.CloseButton aria-label="모달 닫기" />
// ✅ 조건부로 푸터 표시
<Modal>
<Modal.Header>제목</Modal.Header>
<Modal.Content>내용</Modal.Content>
{showFooter && (
<Modal.Footer>
<Button>확인</Button>
</Modal.Footer>
)}
</Modal>
try {
await handleSubmit();
closeModal();
} catch (error) {
// 에러 처리
openModal(
<Modal.Content>
<p>처리 중 오류가 발생했습니다.</p>
</Modal.Content>
);
}