Dialog
답할 때까지 페이지를 가져가는 시트.
import { Button, Dialog, DialogClose } from 'neba';
<Dialog
trigger={<Button color="danger">워크스페이스 삭제</Button>}
title="이 워크스페이스를 삭제할까요?"
description="안에 있는 프로젝트·배포·로그가 함께 사라집니다."
actions={<DialogClose render={<Button color="danger">삭제</Button>} />}
>
되돌릴 수 없습니다.
</Dialog>;Props
| Prop | 타입 | 기본값 | 설명 |
|---|---|---|---|
| size공통 | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'md' | 타입 스케일과 여백, 그리고 시트가 넓어질 수 있는 한계까지 함께 정합니다. maxWidth라는 두 번째 축을 만들지 않은 이유입니다 |
| color공통 | 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info' | 'primary' | 의미론적 색 역할. 시트는 물들지 않으므로 가장자리와 포커스 링에만 나타납니다 |
| density공통 | 'default' | 'compact' | 'default' | 여백만 바꿉니다 |
| open | boolean | — | 열림 여부. onOpenChange와 함께 쓰면 제어 컴포넌트가 됩니다 |
| defaultOpen | boolean | false | 비제어 다이얼로그의 초기 상태 |
| onOpenChange | (open: boolean) => void | — | 열리거나 닫힐 때 호출 |
| trigger | ReactElement | — | 다이얼로그를 여는 요소. Base UI가 연결합니다. 선택 사항 — 다른 곳에서 여는 제어 다이얼로그에는 필요 없습니다 |
| title | ReactNode | — | 제목. 다이얼로그의 이름이 되는 h2로 렌더링됩니다 |
| description | ReactNode | — | 제목 아래 한 줄이자 다이얼로그의 접근성 설명 |
| actions | ReactNode | — | 아래쪽 버튼 줄. 끝 정렬됩니다. DialogClose가 그중 하나를 닫기 버튼으로 만듭니다 |
| dividers | boolean | false | 구역 사이를 여백 대신 하이라인으로 나눕니다. 본문이 스크롤되는 순간부터 켜는 편이 좋습니다 |
| showClose | boolean | true | 모서리의 ×. 라이브러리의 다른 불리언과 달리 기본이 켜짐입니다 — 모달은 답할 때까지 페이지를 가져가므로 나가는 길이 보여야 합니다 |
| closeLabel | string | 'Close' | × 버튼의 접근성 이름 |
| width | number | string | — | size가 정한 최대 너비를 대신할 값. 숫자는 픽셀입니다 |
| fullWidth | boolean | true | size가 허용하는 너비를 가득 채웁니다. 다른 컴포넌트와 반대로 기본이 켜짐입니다 — 다이얼로그의 컨테이너는 뷰포트입니다 |
| fullScreen | boolean | false | 뷰포트를 가장자리까지 채웁니다 |
| modal | boolean | 'trap-focus' | true | 뒤 페이지를 가져갈지. trap-focus는 스크롤과 클릭은 남기고 포커스만 가둡니다 |
| dismissible | boolean | true | Esc와 바깥 클릭으로 닫히는지. 끄려면 답할 수 있는 actions를 반드시 함께 주세요 |
| children | ReactNode | — | 본문. 스크롤되는 유일한 구역입니다 |
예시
size가 곧 너비입니다
스크롤되는 본문
스크롤되는 것은 본문뿐이고 제목과 액션은 제자리에 남습니다. 여기서 dividers가 진짜로 하는 일이 그것입니다 — 헤더가 움직이지 않았다고 말해 주는 것이 그 하이라인입니다.
반드시 답해야 하는 다이얼로그
dismissible={false}는 Esc와 바깥 클릭을 함께 끕니다. 답할 수 있는 액션이 있을 때만 끄세요. 그 외에는 나갈 방법이 없습니다.
상태를 들지 않고 닫기
비제어 다이얼로그에는 Cancel 버튼이 호출할 setOpen이 없고, 그렇다고 모든 다이얼로그를 제어형으로 만들면 버튼 하나에 답하기 위한 상태가 다이얼로그마다 하나씩 생깁니다. DialogClose가 그 출구입니다. Base UI의 close 파트 그대로이므로 render로 진짜 Neba 버튼을 안에 넣을 수 있습니다.
actions={
<>
<DialogClose render={<Button variant="text" color="secondary">취소</Button>} />
<DialogClose render={<Button color="danger">삭제</Button>} />
</>
}크기 축은 하나입니다
MUI는 이것을 size와 maxWidth로 나눕니다. 여기서는 하나입니다. size가 타입 스케일과 여백은 물론 시트가 넓어질 수 있는 한계까지 정합니다. 다섯 값짜리 스케일을 하나 더 만드는 것은 이미 이름이 있는 개념에 두 번째 철자를 만드는 일입니다 — Prop 규약을 보세요.
다만 그 분리가 존재하는 이유 자체는 실제 상황입니다. 표나 diff를 담는, 작은 글씨에 넓은 시트. 그것이 width이고, 스케일이 아니라 그냥 숫자이므로 무엇과도 보조를 맞출 필요가 없습니다.
없는 것
variant가 없습니다. 세 가지 무게는 "이 표면이 주변 페이지에 대해 얼마나 자기를 주장하는가"에 답하는 축인데, 모달은 이미 페이지를 통째로 가져갔습니다.
elevation도 없습니다. 팝업은 라이브러리에서 떠 있어야 마땅한 두 표면 중 하나이므로 언제나 3단계 그림자를 답니다. 평평하게 두라고 시킬 수 있는 다이얼로그는 다이얼로그이기를 그만두라고 시킬 수 있는 다이얼로그입니다.
접근성
어려운 부분은 전부 Base UI가 가집니다 — 포커스 트랩, 스크롤 잠금, 뒤 페이지 비활성화, 닫을 때 트리거로 포커스 되돌리기, 그리고 title과 description을 aria-labelledby·aria-describedby로 잇는 일. 제목은 진짜 <h2>이므로 다이얼로그가 문서 개요에 제대로 나타납니다.
showClose는 이 라이브러리의 다른 불리언과 달리 기본이 켜짐입니다. 모달은 답할 때까지 페이지를 가져가고, 나가는 길은 기억해 내야 하는 것이 아니라 보여야 합니다. 터치 스크린 리더가 팝업에서 빠져나오는 통로이기도 합니다.