Get startedFoundationsComponentsPatternsRules

Modal Dialog

모달 다이얼로그는 페이지 위 레이어에 떠서 사용자의 응답이 필요한 내용을 보여줘요.

설치

pnpm dlx shadcn@latest add https://rebar.conmarket-landing.workers.dev/r/steel/modal-dialog.json

Examples

Default

ModalDialog 안에 ModalHeader, ModalBody, ModalFooter 를 순서대로 넣어요. ModalTransition 으로 감싸고 {isOpen && <ModalDialog />} 로 열고 닫으면 닫힐 때도 퇴장 애니메이션이 끝까지 재생돼요. 열릴 때는 블랭킷과 함께 페이드 인되면서 대화상자가 95% 에서 100% 로 커지고(250ms), 닫힐 때는 100% 에서 95% 로 줄며 사라져요(200ms). 전체 화면 모드도 같아요.

Appearance

ModalTitle 의 appearance 를 warning 이나 danger 로 주면 제목 앞에 아이콘이 붙어요. 색은 모달이 자동으로 바꿔주지 않으니 주요 버튼의 appearance 도 같은 값으로 맞춰요.

Appearance용도
warning되돌릴 수 있지만 영향이 큰 변경을 알릴 때
danger삭제처럼 파괴적이거나 되돌릴 수 없는 작업을 확인할 때

Width

width 로 이름 있는 크기를 골라요. 숫자(px)나 CSS 문자열도 받을 수 있지만 이름 있는 크기를 권장해요. 화면 폭이 30rem(480px)보다 좁으면 모달이 화면을 꽉 채워요.

Width크기
small400px
medium600px (기본값)
large800px
x-large968px

Full screen

FullScreenModalDialog 는 위아래·좌우 여백 없이 화면 전체를 채워요. 헤더와 닫기 버튼이 항상 보이도록 본문만 스크롤되고, 블랭킷 클릭으로는 닫히지 않아요.

Scrolling behavior

기본적으로 내용이 길면 모달 본문이 스크롤되고, 헤더·푸터는 고정된 채 위아래에 구분선(keyline)이 생겨요. shouldScrollInViewport 를 주면 모달 전체가 늘어나고 화면(viewport) 이 스크롤돼요.

Focus management

열리면 첫 번째 상호작용 요소(보통 헤더의 닫기 버튼)로 포커스가 가요. 특정 요소에 먼저 포커스를 주려면 autoFocus 에 그 요소의 ref 를 넘겨요. 닫히면 모달을 연 요소로 포커스가 돌아가요.

Form

form 을 ModalDialog 의 유일한 자식으로 두면 모달 레이아웃(세로 flex, 최대 높이)을 그대로 이어받아요. 푸터에 type="submit" 버튼을 두면 Enter 로도 제출돼요.

Custom header

useModal() 로 onClose 와 titleId 를 꺼내 헤더를 직접 만들 수 있어요. 닫기 버튼은 CloseButton 을 쓰고, 화면에서는 오른쪽에 있어도 DOM 에서는 먼저 오도록 flex-row-reverse 로 배치해요.

ModalFooter 에는 버튼 외의 요소도 넣을 수 있어요. 부가 정보는 왼쪽에, 버튼은 오른쪽에 둬요.

Usage guidelines

모달은 지금 보고 있는 페이지의 맥락을 잃지 않고 바로 끝내야 하는 작업을 보여줄 때 써요. 응답이 꼭 필요한 중요 정보나 경고, 작업을 마치는 데 필요한 보조 액션이 여기에 해당해요. 모달이 열려 있는 동안에는 뒤 페이지를 쓸 수 없어서 흐름을 끊기 때문에 꼭 필요할 때만 써요.

구성

  1. Header — 모달 제목이 들어가요. 제목은 항상 h1 이에요.
  2. Close button — 헤더 끝에서 모달을 닫아요.
  3. Body — 모달의 목적을 설명하고 작업에 필요한 입력 요소를 담아요.
  4. Footer — 주요 액션과 취소(닫기) 버튼이 들어가요.

언제 쓰나요

  • 한 가지 짧은 작업이나 메시지에 집중시킬 때
  • 계속하기 전에 확인이 필요한 경고·위험 작업
  • 필터나 힌트 같은 보조 정보는 넣어도 되지만 짧게 유지해요.

복잡한 상호작용, 큰 표, 여러 단계로 넘어가는 흐름에는 맞지 않아요. 이럴 때는 별도 페이지를 고려해요.

모범 사례

  • 작업과 관계없는 요소는 빼서 상호작용을 최소화해요.
  • 모달 안에서 여러 단계를 오가는 흐름은 피해요.
  • 작업을 끝내는 데 필요한 정보는 모두 모달 안에 담아요. 모달 밖의 정보에 기대지 않아요.
  • 닫는 방법을 여러 개 제공해요. 헤더의 닫기 버튼은 필수, 푸터의 취소 버튼은 선택이에요.
  • 가로 스크롤은 피하고 세로 스크롤도 최소화해요.

버튼 배치

  • 푸터 버튼은 오른쪽에 정렬해요.
  • 버튼이 여러 개면 주요 버튼을 보조 버튼의 오른쪽에 둬요.
Do· 하나의 작업에 집중
제목과 본문을 짧게 쓰고 한 가지 작업이나 메시지만 다뤄요.
Don't· 복잡한 내용
복잡한 상호작용이나 큰 표를 모달에 넣지 마세요.
Do· 한 번에 하나
블랭킷 위에 모달을 하나만 띄워요.
Don't· 모달 위에 모달
모달에서 또 다른 모달을 열면 혼란스럽고 접근성도 떨어져요. 새 탭으로 열거나 현재 모달을 닫은 뒤 이어가요.

문구 작성

  • 본문에는 꼭 필요하고 관련 있는 정보만 담아요.
  • 버튼 라벨은 누르면 일어나는 일을 동사로 써요. (예: "담당자" 대신 "담당자 선택")
  • 주요 버튼 라벨은 제목과 맞춰요. 제목이 "프로젝트를 삭제할까요?" 라면 버튼은 "삭제" 예요.

관련 컴포넌트

  • 적은 양의 정보와 컨트롤을 곁들일 때는 Popup 을 써요.
  • 중요한 정보나 필요한 조치를 알릴 때는 Inline Message 를 써요.
  • 페이지를 유지한 채 옆에서 보조 작업을 할 때는 Drawer 를 고려해요.

Accessibility

  • 제목은 필수예요. ModalTitle 을 쓰거나, 직접 만든 제목에 useModal() 의 titleId 를 id 로 붙여요. 보이는 제목이 정말 없을 때만 label 을 써요.
  • 심각도를 색으로만 전달하지 않아요. appearance 아이콘에는 "경고"·"위험" 이라는 대체 텍스트가 붙어요.
  • 닫는 방법: 헤더 닫기 버튼, Esc, 블랭킷 클릭, (선택) 푸터의 취소 버튼.
  • 포커스 순서: 닫기 버튼 → 본문의 입력·상호작용 요소 → 보조 버튼 → 주요 버튼. 포커스는 모달 안에 갇히고, 닫히면 모달을 연 요소로 돌아가요.
  • 본문이 스크롤되면 스크롤 영역이 "스크롤 가능한 내용" 이라는 이름의 region 이 되어 키보드로도 스크롤할 수 있어요.
  • 모달은 role="dialog", aria-modal="true" 로 렌더링되고 뒤 콘텐츠는 보조 기술에서 숨겨져요.

Props

ModalDialog

Prop

Type

ModalHeader

Prop

Type

ModalTitle

Prop

Type

ModalBody

Prop

Type

ModalFooter · ModalTransition · CloseButton · useModal

Prop

Type

On this page