Modal
넓은 화면에서는 Dialog, 좁은 화면에서는 BottomSheet로 열려요. 추가, 수정처럼 PC와 모바일에서 모양만 다른 창에 써요. 안의 내용은 한 번만 작성해요.
사용 예시
일정 추가
창 폭이 480px 이상이면 가운데에, 좁으면 아래에서 열려요. 푸터 버튼은 Dialog 모양에서는 오른쪽에 모이고, BottomSheet 모양에서는 같은 폭으로 나뉘어요.
tsx
모양에 따라 내용 바꾸기
useModalShape()로 지금 모양을 알 수 있어요. Dialog 모양에서는 헤더에 단계를 글자로, BottomSheet 모양에서는 본문 위에 Progress로 보여요. 화면 폭 조건을 따로 적지 않아도 Modal과 같은 기준을 써요.
tsx
수정
저장처럼 누른 뒤 값을 반영하고 닫아야 하면 open을 넘기고 호출하는 쪽에서 닫아요. 열 때 입력값을 지금 이름으로 되돌려서 그대로 두기로 닫은 내용이 남지 않게 해요.
프로젝트: 신제품 출시
tsx
한쪽 모양으로 고정
as를 dialog나 sheet로 주면 화면 폭과 상관없이 그 모양으로 열려요. 한 화면에서 같은 창이 늘 같은 모양이어야 할 때 써요.
tsx
기준 폭 바꾸기
size lg처럼 넓은 창은 breakpoint를 md로 올려서 768px 아래에서는 BottomSheet로 열어요.
tsx
권장
되돌릴 수 없는 동작은 AlertDialog로 물어요. 화면 폭과 상관없이 가운데에 열리고 바깥을 눌러도 닫히지 않아요.
지양
Modal은 바깥을 누르거나 BottomSheet 모양에서 스와이프하면 답하지 않고 닫혀요.
컨트롤
tsx
명세
| 이름 | 값 | 기본 |
|---|---|---|
| Modal | ||
| open | boolean | - |
| 호출하는 쪽에서 열림 상태를 관리해요. 열린 상태로 breakpoint를 넘으면 모양만 바뀌고 계속 열려 있어요. 이때 안쪽을 다시 그려서 저장하지 않은 입력값은 없어져요. | ||
| defaultOpen | boolean | false |
| 처음에 열어 둘지 정해요. | ||
| onOpenChange | (open: boolean, eventDetails) => void | - |
| 열리거나 닫히면 호출돼요. BottomSheet 모양에서 스와이프로 닫으면 eventDetails.reason이 swipe예요. | ||
| breakpoint | xs, sm, md | xs |
| 이 폭 이상이면 Dialog, 아래면 BottomSheet로 열려요. xs는 480px, sm은 640px, md는 768px이에요. | ||
| as | auto, dialog, sheet | auto |
| auto는 breakpoint로 모양을 고르고, dialog와 sheet는 화면 폭과 상관없이 그 모양으로 열어요. | ||
| render | ReactElement | - |
| 기본 요소 대신 그릴 요소예요. ModalTrigger와 ModalClose에 Button을 넘길 때 써요. | ||
| className | string | - |
| Modal을 뺀 모든 하위 컴포넌트에 쓸 수 있어요. | ||
| ModalContent | ||
| size | sm, md, lg | md |
| Dialog 모양일 때의 최대 너비예요. sm은 448px, md는 480px, lg는 640px이에요. BottomSheet 모양에서는 쓰지 않아요. | ||
| ModalHeader | ||
| lead | ReactNode | - |
| 제목 앞에 보여요. | ||
| trail | ReactNode | - |
| 헤더 오른쪽 끝에 보여요. | ||
| closable | boolean | false |
| 헤더 오른쪽 끝에 닫기 버튼을 보여요. trail이 있으면 trail 다음에 와요. | ||
| closeLabel | string | 닫기 |
| 닫기 버튼의 접근성 이름이에요. | ||
| ModalBody | ||
| children | ReactNode | - |
| 본문이에요. 길면 헤더와 ModalFooter는 그대로 두고 이 안에서만 스크롤돼요. | ||
| ModalFooter | ||
| layout | end, between, fill, grow-last, { narrow, wide } | 모양에 따라 |
| Dialog 모양이면 end로 오른쪽에 모으고, BottomSheet 모양이면 fill로 버튼이 같은 폭으로 나뉘어요. 값 하나를 넘기면 모양과 상관없이 그 배치를 쓰고, { narrow, wide }를 넘기면 Dialog 모양에서는 wide, BottomSheet 모양에서는 narrow를 써요. | ||
| useModalShape | ||
| 반환값 | 'dialog', 'sheet', null | - |
| Modal 안에서 부르면 지금 모양을, 밖에서 부르면 null을 돌려줘요. breakpoint와 as가 정한 모양과 항상 같아요. | ||