슬롯
DialogTrigger · DialogContent · DialogHeader · DialogTitle · DialogDescription · DialogFooter · DialogClose
ConfirmDialog
open · onOpenChange · tone(default|destructive) · confirmLabel · onConfirm(async)
포커스 트랩
Radix 자동 — 열릴 때 첫 포커스 이동, 닫힐 때 트리거로 복귀
showCloseButton
DialogContent prop — X 버튼 표시 여부 (기본 false)
라이브 검증
DialogTrigger asChild + ConfirmDialog open/onOpenChange 패턴으로 실제 열기/닫기 확인 필요
Dismiss policy
X 버튼을 사용하지 않습니다. 닫기 방법은 footer 버튼(explicit) + 바깥 클릭(passive) + Esc(keyboard) 세 가지입니다. simple은 확인 1버튼, standard는 confirm pair, 파괴적 액션은 `<ConfirmDialog>`를 사용합니다.

Simple (안내형)

라이브 (X button 없음 — 확인 버튼만. 단순 안내 · 정보 전달용)
코드 보기tsx
import {
  Dialog, DialogTrigger, DialogContent,
  DialogHeader, DialogTitle, DialogDescription, DialogFooter, DialogClose,
} from "@olundot/ui";
import { Button } from "@olundot/ui";

// simple variant: showCloseButton 없음 (기본 false) — X 버튼 미표시.
// 단순 안내 · 정보 전달에 사용. Cancel 버튼 하나로 dismiss.
// outside click / Esc 로도 닫힘 (Radix 기본).
// DialogContent 기본 패딩 = var(--space-4) (32px).
export function DialogSimple() {
  return (
    <Dialog>
      <DialogTrigger asChild>
        <Button variant="outline">안내 보기</Button>
      </DialogTrigger>
      <DialogContent>
        <DialogHeader>
          <DialogTitle>응시 안내</DialogTitle>
          <DialogDescription>
            시험은 60분 제한이며, 제한 시간 종료 시 자동 제출됩니다.
            안정적인 네트워크 환경에서 응시하세요.
          </DialogDescription>
        </DialogHeader>
        <DialogFooter>
          <DialogClose asChild>
            <Button variant="outline">확인</Button>
          </DialogClose>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}

Standard (표준)

라이브 (X 버튼 없음 — Cancel + Submit + 바깥 클릭 / Esc 로 닫기)
코드 보기tsx
import { useState } from "react";
import {
  Dialog, DialogTrigger, DialogContent,
  DialogHeader, DialogTitle, DialogDescription, DialogFooter, DialogClose,
} from "@olundot/ui";
import { Button } from "@olundot/ui";

// standard variant: 닫기 버튼 미사용 정책 (showCloseButton 사용 안 함).
// dismiss = footer Cancel (explicit user intent) + outside click (passive) + Esc (keyboard).
// 폼 입력 · 데이터 등록 등 일반적인 작업에 사용.
export function DialogStandard() {
  const [open, setOpen] = useState(false);
  return (
    <Dialog open={open} onOpenChange={setOpen}>
      <DialogTrigger asChild>
        <Button variant="primary">메모 추가</Button>
      </DialogTrigger>
      <DialogContent>
        <DialogHeader>
          <DialogTitle>학습 메모 추가</DialogTitle>
          <DialogDescription>이 문항에 대한 학습 노트를 남깁니다.</DialogDescription>
        </DialogHeader>
        <div style={{ display: "grid", gap: "12px" }}>
          <label style={{ display: "grid", gap: "4px", fontSize: "0.875rem" }}>
            <span>제목</span>
            <input
              type="text"
              placeholder="메모 제목"
              style={{
                padding: "8px 12px",
                borderRadius: "var(--radius-md)",
                border: "1px solid var(--border-subtle)",
                background: "var(--bg-surface)",
                color: "var(--text-primary)",
              }}
            />
          </label>
          <label style={{ display: "grid", gap: "4px", fontSize: "0.875rem" }}>
            <span>내용</span>
            <textarea
              rows={3}
              placeholder="학습 메모를 입력하세요"
              style={{
                padding: "8px 12px",
                borderRadius: "var(--radius-md)",
                border: "1px solid var(--border-subtle)",
                background: "var(--bg-surface)",
                color: "var(--text-primary)",
                resize: "vertical",
              }}
            />
          </label>
        </div>
        <DialogFooter>
          <DialogClose asChild>
            <Button variant="outline">취소</Button>
          </DialogClose>
          <Button variant="primary">저장</Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}

Destructive (ConfirmDialog)

라이브 (ConfirmDialog — destructive tone + async onConfirm + loading 상태)
코드 보기tsx
import { useState } from "react";
import { ConfirmDialog } from "@olundot/ui";
import { Button } from "@olundot/ui";

// destructive variant: ConfirmDialog 전용 컴포넌트 사용.
// 비가역 액션(삭제·취소·초기화)에서 명시적 confirm 요구.
// onConfirm async 지원 — loading 상태 자동 처리.
export function DialogDestructive() {
  const [open, setOpen] = useState(false);
  return (
    <div style={{ display: "flex", gap: "8px" }}>
      <Button variant="destructive" onClick={() => setOpen(true)}>
        수강 취소
      </Button>
      <ConfirmDialog
        open={open}
        onOpenChange={setOpen}
        title="수강을 취소하시겠습니까?"
        description="취소 후에는 해당 강의에 접근할 수 없게 됩니다."
        tone="destructive"
        confirmLabel="수강 취소"
        cancelLabel="돌아가기"
        onConfirm={async () => {
          await new Promise((r) => setTimeout(r, 1500));
        }}
      />
    </div>
  );
}