Modal
다양한 형태로 콘텐츠를 표시하는 모달 컴포넌트
개요
Modal 컴포넌트는 사용자에게 추가 콘텐츠나 작업을 표시하기 위한 오버레이 UI입니다. Center, Fullscreen, Bottomsheet, Sidepanel 4가지 타입을 지원하며, 딤 처리와 배경 인터랙션 허용 등 세밀한 제어가 가능합니다.
주요 특징
- ✅ 4가지 타입: center, fullscreen, bottomsheet, sidepanel
- ✅ 딤 제어: 배경 딤 처리 on/off
- ✅ 배경 인터랙션: 모달 열린 상태에서 배경 상호작용 허용
- ✅ 커스텀 Footer: footer prop으로 액션 버튼 영역 구성
- ✅ 닫기 버튼: showCloseButton으로 닫기 버튼 표시
- ✅ 드래그 가능: center/fullscreen 타입에서 드래그 지원
- ✅ 리사이즈 가능: center 타입에서 드래그로 크기 조절 지원
- ✅ 디자인 토큰: 테마 커스터마이징 지원
Types
Modal은 4가지 타입을 지원합니다.
Center
기본 중앙 모달입니다. 확인/입력 등 일반적인 대화 상자에 적합합니다.
Preview
Fullscreen
전체 화면 모달입니다. 긴 콘텐츠나 복잡한 작업에 적합합니다.
Preview
Bottomsheet
하단에서 올라오는 시트입니다. 모바일 환경이나 간단한 선택 작업에 적합합니다.
Preview
Sidepanel
오른쪽에서 슬라이드되는 패널입니다. 상세 정보나 설정 화면에 적합합니다.
Preview
Type 설명
| Type | 설명 | 사용 사례 |
|---|---|---|
| center | 화면 중앙에 표시 | 확인/입력 대화 상자, 알림 |
| fullscreen | 전체 화면으로 표시 | 복잡한 작업, 긴 콘텐츠 |
| bottomsheet | 하단에서 올라오는 시트 | 모바일 선택, 간단한 입력 |
| sidepanel | 오른쪽에서 슬라이드 | 상세 정보, 설정, 필터 패널 |
사용 예시
Dim 없는 Modal
dim={false}로 배경 딤 처리를 비활성화할 수 있습니다.
Preview
배경 인터랙션 허용
allowInteraction을 활성화하면 모달이 열린 상태에서도 배경과 상호작용할 수 있습니다.
Preview
리사이즈 가능 Modal
resizable을 활성화하면 모달의 가장자리나 모서리를 드래그하여 크기를 조절할 수 있습니다. center 타입에서만 동작하며, fullscreen 타입에서는 비활성화됩니다.
Preview
커스텀 Footer
footer prop으로 액션 버튼 등 커스텀 Footer 영역을 구성할 수 있습니다.
Preview
API Reference
Props
| Prop | Type | Default | Description |
|---|---|---|---|
open | boolean | - | 모달 열림/닫힘 상태 |
type | "center" | "fullscreen" | "bottomsheet" | "sidepanel" | "center" | 모달 표시 타입 |
dim | boolean | true | 배경 딤 처리 여부 |
allowInteraction | boolean | false | 모달 열린 상태에서 배경 인터랙션 허용 |
title | React.ReactNode | - | 모달 헤더 제목 |
description | React.ReactNode | - | 모달 헤더 설명 |
children | React.ReactNode | - | 모달 본문 콘텐츠 |
footer | React.ReactNode | - | 모달 하단 영역 (액션 버튼 등) |
showCloseButton | boolean | false | 우측 상단 닫기 버튼 표시 |
resizable | boolean | false | 드래그로 크기 조절 허용 (center만) |
className | string | - | 추가 CSS 클래스 |
Events
| Event | Type | Description |
|---|---|---|
onOpenChange | (open: boolean) => void | 모달 열림/닫힘 상태 변경 |
기본 사용법
import { useState } from "react"
import { Modal, Button } from "@vortex/ui-foundation"
const [open, setOpen] = useState(false)
<Button onClick={() => setOpen(true)}>Modal 열기</Button>
<Modal
open={open}
onOpenChange={setOpen}
type="center"
title="제목"
description="설명"
>
<div className="p-4">콘텐츠</div>
</Modal>useDialog를 통한 명령형 호출
useDialog 스토어의 modal 메서드를 사용하면 컴포넌트 상태 없이 명령형으로 모달을 열 수 있습니다.
import { useDialog } from "@vortex/ui-foundation"
const { modal } = useDialog()
// 기본 호출
await modal({
title: "제목",
description: "설명",
content: <p>콘텐츠</p>,
})
// close 콜백 활용
await modal({
title: "확인",
content: ({ close }) => (
<div>
<p>내용</p>
<Button onClick={close}>닫기</Button>
</div>
),
footer: ({ close }) => (
<div className="flex gap-2">
<Button variant="outline" onClick={close}>취소</Button>
<Button onClick={close}>확인</Button>
</div>
),
type: "center",
dim: true,
})접근성
키보드 내비게이션
- Escape: 모달 닫기 (allowInteraction이 아닌 경우)
- Tab: 모달 내부 포커스 이동
권장 사항
- ✅
titleprop으로 모달의 목적을 명확히 전달 - ✅
description으로 추가 맥락 제공 - ✅ 닫기 동작을 명확하게 제공 (
showCloseButton또는 footer 버튼) - ✅ Fullscreen 모달에는 반드시
showCloseButton사용 - ❌ 배경 인터랙션 허용 시 닫기 수단 없이 사용 지양
관련 컴포넌트
Modal vs Dialog
| 항목 | Modal | Dialog |
|---|---|---|
| 역할 | 4가지 타입을 통합한 고수준 모달 컴포넌트 | 기본 대화 상자 프리미티브 |
| 타입 | center, fullscreen, bottomsheet, sidepanel | center만 지원 |
| useDialog | modal() 메서드로 명령형 호출 가능 | 직접 사용 시 수동 상태 관리 필요 |
| 사용 사례 | 통합 모달 UI가 필요할 때 | 단순 대화 상자가 필요할 때 |
Last updated on