dialog
화면 가운데 뜨는 확인 대화상자와 아래에서 올라오는 메뉴를 함수 호출 하나로 여는 도구다. 결과(눌린 버튼)를 약속(Promise)으로 돌려준다.
- 분류
- 알림과 안내
- 가져오기
import { DialogHost, DialogCard } from '@/ui/dialog'- 코드 위치
apps/mobile/src/ui/dialog.tsx:73
미리보기#
실제 컴포넌트를 화면에 그린 것이다. 화면 아래의 서비스 색 선택기로 색을 바꿔 볼 수 있다. 버튼과 입력 칸은 직접 눌러 볼 수 있다.
저장했어요
오답 노트에서 다시 볼 수 있어요.
이 자료를 열까요?
지금까지 푼 기록은 그대로 남아요.
자료를 삭제할까요?
문제와 풀이 기록이 모두 사라져요. 되돌릴 수 없어요.
자료 관리
언제 쓰는가#
쓴다
- 알려야 하고 꼭 확인받아야 하는 일에
dialog.alert를 쓴다. - "삭제할까요?" 같은 확인에는
dialog.confirm을 쓴다. 되돌릴 수 없는 일은tone: "danger"로 한다. - 선택지 여러 개를 세로로 늘어놓으려면
dialog.choose, 행동 목록(이름 바꾸기, 삭제)은dialog.menu를 쓴다.
쓰지 않는다
- 사용자를 막지 않아도 되는 알림에는 쓰지 않는다.
toast나Notice를 쓴다. - 대화상자 위에 대화상자를 연속으로 띄우지 않는다. 연속으로 부르면 하나씩 차례로 뜬다.
- 긴 입력이나 양식을 넣지 않는다.
Sheet를 쓴다.
종류#
| 이름 | 설명 |
|---|---|
| dialog.alert | 제목, 본문, 버튼 하나("확인"). 닫으면 끝. |
| dialog.confirm | 취소와 확인 버튼 두 개가 가로로 놓인다. 확인을 누르면 true. |
| dialog.choose | 선택지가 세로로 쌓이고 맨 아래에 취소가 붙는다. 고른 번호를 돌려준다. |
| dialog.menu | 아래에서 올라오는 메뉴 시트. 행마다 아이콘, 이름, 보조 글. |
크기#
| 이름 | 값 | 설명 |
|---|---|---|
| 대화상자 | 폭 최대 420, 좌우 28 여백 | 안쪽 여백 22(위 24). 버튼 높이 48. |
| 메뉴 | 행 최소 높이 56 |
상태#
| 상태 | 모습과 동작 |
|---|---|
| 열림 | 대화상자는 180ms 동안 0.96배에서 1배로 커지며 나타난다. 메뉴는 220ms 동안 올라온다. |
| 닫힘 | 130ms. 바깥을 누르거나 뒤로 가기를 누르면 닫히고 취소(false/null)로 처리된다. |
| 여러 개 호출 | 순서대로 하나씩 뜬다(대기열). |
사용 방법#
앱 맨 위에 한 번 놓기
앱 맨 위에 한 번 놓기
import { DialogHost } from '@/ui/dialog';
// 루트 레이아웃에서 한 번만 렌더링한다.
<DialogHost />확인받기
확인받기
import { dialog } from '@/ui/dialog';
const ok = await dialog.confirm({
title: '자료를 삭제할까요?',
body: '문제와 풀이 기록이 모두 사라져요. 되돌릴 수 없어요.',
confirmLabel: '삭제',
tone: 'danger',
icon: Trash2,
});
if (ok) await remove();알림과 메뉴
알림과 메뉴
await dialog.alert('저장했어요', '오답 노트에서 다시 볼 수 있어요.');
const i = await dialog.menu({
title: '자료 관리',
options: [
{ label: '이름 바꾸기', icon: Pencil },
{ label: '삭제', icon: Trash2, tone: 'danger' },
],
});
if (i === 1) await remove();속성(props)#
| 함수 | 형태 | 설명 |
|---|---|---|
dialog.alert | (title: string, body?: string, label = '확인'): Promise<void> | 알림. 닫힐 때 끝나는 약속을 돌려준다. |
dialog.confirm | ({ title, body, confirmLabel = '확인', cancelLabel = '취소', tone = 'primary', icon }: { title: string; body?: string; confirmLabel?: string; cancelLabel?: string; tone?: 'primary' | 'danger'; icon?: Icon; }): Promise<boolean> | 확인. 확인을 눌렀으면 true, 취소하거나 바깥을 눌렀으면 false. |
dialog.choose | ({ title, body, options, cancelLabel = '취소', icon, tone }: { title: string; body?: string; options: Option[]; cancelLabel?: string | null; icon?: Icon; tone?: Tone; }): Promise<number | null> | 선택지 목록. 고른 번호(0부터), 취소면 null. |
dialog.menu | ({ title, body, options }: { title: string; body?: string; options: Option[] }): Promise<number | null> | 메뉴 시트. 고른 번호, 닫으면 null. |
DialogHost
속성이 없다.
DialogCard
| 이름 | 타입 | 기본값 | 필수 | 설명 |
|---|---|---|---|---|
children | ReactNode | — | 필수 | 카드 안의 내용. 대화상자와 같은 면(surface, 모서리 24, shadow(3))을 직접 그릴 때 쓴다. |
DialogHost는 속성이 없다. 앱 루트에 한 번 두면 dialog.* 호출을 받아 그린다. 선택지 항목(Option)은 { label, tone?: "primary" | "danger" | "neutral", icon?, detail? }이다.
치수와 토큰#
- 대화상자
surface, 모서리radius.sheet(24), 안쪽 22(위 24),shadow(3), 좌우 28 여백, 최대 폭 420- 아이콘 타일
- 44 × 44, 모서리 14, 톤 색 12% 투명도, 아이콘 22 선 2.2
- 제목과 본문
- 제목
headline, 본문bodytextSecondary(제목 아래 6) - 버튼
- 높이 48, 모서리 14, 둘이면 가로로 같은 폭, 그 밖에는 세로로 쌓기(사이 8). neutral은
segmentTrack바탕, primary는primary, danger는danger - 메뉴
card바탕 목록, 행 최소 56, 아이콘 타일 34(색 10%)- 어둠막
scrim
접근성#
- 대화상자의 역할은
alert이고 모달이다(accessibilityViewIsModal). - 버튼에는 이름(글자)이 있고 글자가 길면 80%까지 줄어든다.
- 위험한 확인(
danger)은 색, 아이콘, 제목·본문 글자로 함께 알린다. - Android 뒤로 가기는 닫기와 같다.
글자 색 대비
글자 크기별 기준: 작은 글자는 4.5:1 이상, 큰 글자(굵은 18.66px 이상)는 3:1 이상이다. 값은 선택한 서비스와 모드의 토큰으로 계산했다.
| 쓰임 | 글자색 | 바탕 | 대비 | 기준 |
|---|---|---|---|---|
| primary 버튼 글자 (15px 굵게) | onPrimary | primary | 3.93:1 미달3.31:1 미달4.60:1 통과7.25:1 통과 | 4.5:1 (작은 글자) |
| danger 버튼 글자 (15px 굵게) | onDanger | danger | 4.55:1 통과3.02:1 미달5.15:1 통과7.36:1 통과 | 4.5:1 (작은 글자) |
| neutral 버튼 글자 (15px 굵게) | text | segmentTrack | 15.54:1 통과14.08:1 통과14.95:1 통과9.62:1 통과 | 4.5:1 (작은 글자) |
| 본문 (15px) | textSecondary | surface | 4.23:1 미달6.95:1 통과4.88:1 통과7.11:1 통과 | 4.5:1 (작은 글자) |
잘한 예와 잘못한 예#
자료를 삭제할까요?
기록이 모두 사라져요.
danger로 한다.저장할 때마다 뜨는 확인 대화상자
toast로 충분하다.함께 보는 컴포넌트#
- Sheet: 화면 아래에서 올라오는 시트다. 위쪽 두 모서리가 둥글고, 손잡이와 제목 줄, 닫기 버튼이 있다.
- toast: 화면 아래에 잠깐 떴다 사라지는 짧은 확인 메시지다. 함수 한 번 호출로 띄운다. 되돌리기 같은 행동 하나를 붙일 수 있다.
- Notice: 화면 안에 끼워 넣는 한 줄 안내 상자다. 안내(파랑), 주의(주황), 오류(빨강) 세 가지 톤이 있다.
- PrimaryButton: 서비스 주색 그라데이션으로 채운 알약 모양 버튼이다. 한 화면에서 가장 중요한 행동 하나에 쓴다.