Modal
오버레이 다이얼로그 — 포커스 트랩 · Escape/배경 닫기 · 포커스 복원 · 스크롤 잠금을 내장한 제어 컴포넌트입니다.
마지막 업데이트 2026-06-11
한눈에#
진행 중인 작업을 멈추고 한 가지 결정을 받는 오버레이 다이얼로그입니다 — 포커스 트랩·Escape/배경 닫기·포커스 복원·스크롤 잠금을 내장한 제어 컴포넌트입니다.
변경사항을 저장할까요?저장하지 않으면 이 페이지의 변경사항이 사라집니다.
- role=dialog · aria-modal
- 포커스 트랩·복원
- Escape·배경 닫기
- 배경 스크롤 잠금
트리거를 눌러 포커스 트랩·Escape·배경 닫기를 직접 확인하세요:
사용 시점#
흐름을 멈추고 한 가지 결정을 받는 차단형 다이얼로그면 Modal — 측면·하단·가벼운 정보는 다른 컴포넌트입니다.
쓴다
삭제 확인·약관 동의처럼 화면 중앙에서 주의를 가두고 한 가지 결정·짧은 폼을 받을 때
해부#
오버레이는 포털로 떠서 인라인 렌더가 안 되므로, 열린 패널을 재현해 토큰 실측을 핀으로 얹습니다(실제 동작은 위 트리거).
변경사항을 저장할까요?저장하지 않으면 변경사항이 사라집니다.
- radius
- 20px
radius.xl - shadow
- shadow.xl
- body padding
- 24px
space-6 - header/footer
- 16 · 24px
space-4 · space-6
플레이그라운드#
컨트롤로 props를 조작하면 미리보기와 코드가 실시간 갱신됩니다.
import { Modal, Button } from '@wds/ui-web';
<Modal
open={open}
onClose={() => setOpen(false)}
title="변경 사항을 저장할까요?"
>
저장하지 않은 변경 사항이 있습니다.
</Modal>변형#
배경 클릭 닫기는 기본 동작이며, 파괴적 확인 등 명시적 선택이 필요한 흐름은
closeOnBackdrop={false}로 끕니다(Escape와 닫기 버튼은 항상 동작).
크기#
sizemax-widthremsm400px25remmd560px35remlg720px45rem
상태#
제어 컴포넌트입니다 — 열림/닫힘은 소비자의 open prop이 결정하고,
닫힘 요청(Escape·배경·닫기 버튼)은 전부 onClose 콜백으로 전달됩니다.
내부에 열림 상태를 갖지 않으므로 URL·폼 흐름과 동기화하기 쉽습니다.
Props#
| Prop | 타입 | 기본값 | 설명 |
|---|---|---|---|
open | boolean | — | 표시 여부 — 제어 prop |
onClose | () => void | — | Escape·배경·닫기 버튼의 닫힘 요청 콜백 |
title | ReactNode | — | 제목 — aria-labelledby 대상이라 필수 |
footer | ReactNode | — | 하단 행동 영역 (우측 정렬) |
size | 'sm' | 'md' | 'lg' | 'md' | 최대 폭 400/560/720px |
closeOnBackdrop | boolean | true | 배경 클릭 닫기 허용 |
closeLabel | string | '닫기' | 닫기 버튼 aria-label |
접근성#
| 계약 | 구현 |
|---|---|
| 역할 | role="dialog" + aria-modal="true" |
| 이름 | title이 aria-labelledby로 연결 |
| 포커스 진입 | 열리면 패널로 이동 |
| 포커스 트랩 | Tab/Shift+Tab이 내부에서 순환 |
| 포커스 복원 | 닫히면 이전 포커스 요소로 복귀 |
| 키보드 닫기 | Escape — 포커스 위치 무관(document 캡처) |
| 스크롤 | 열림 동안 배경 body 스크롤 잠금 |
| 모션 | 등장 애니메이션은 prefers-reduced-motion 존중 |
토큰#
component 토큰 없이 semantic을 직접 소비합니다(신설 기준 §4 미충족 — 폭 3단은 P5 패리티 시 재평가).
| 속성 | 토큰 |
|---|---|
| 오버레이 | color.overlay · z.modal |
| 패널 배경 | color.surface-raised |
| 라운드/그림자 | radius.xl · shadow.xl |
| 닫기 버튼 | hover color.surface-hover · pressed color.surface-pressed |
| 등장 모션 | duration.fast/normal · 패널 ease.emphasized-decelerate · 스크림 ease.out |