상태 제어
open과 onOpenChange를 필수로 받아 호출부가 열림 상태를 소유합니다.
tone
default는 일반 승인, destructive는 삭제·취소처럼 위험한 action에 사용합니다.
onConfirm
동기와 비동기 함수를 모두 지원하며 처리 중에는 중복 실행과 닫기를 막습니다.
레이블
confirmLabel은 action 결과를 구체적으로 말해야 합니다. '확인'만으로 끝내지 않습니다.

기본 확인

기본 tone과 비동기 확인
코드 보기tsx
import { useState } from "react";
import { Button, ConfirmDialog } from "@olundot/ui";

export function ConfirmDialogDefault() {
  const [open, setOpen] = useState(false);
  const [confirmed, setConfirmed] = useState(false);

  return (
    <div style={{ display: "grid", gap: "12px" }}>
      <Button variant="primary" onClick={() => setOpen(true)}>
        승인 요청
      </Button>
      <ConfirmDialog
        open={open}
        onOpenChange={setOpen}
        title="요청을 승인할까요?"
        description="승인하면 담당자에게 검토 완료 알림이 전송됩니다."
        confirmLabel="승인"
        cancelLabel="취소"
        onConfirm={async () => {
          await new Promise((resolve) => setTimeout(resolve, 800));
          setConfirmed(true);
        }}
      />
      {confirmed ? <p>승인 처리되었습니다.</p> : null}
    </div>
  );
}

파괴적 확인

destructive tone과 구체적인 action label
코드 보기tsx
import { useState } from "react";
import { Button, ConfirmDialog } from "@olundot/ui";

export function ConfirmDialogDestructive() {
  const [open, setOpen] = useState(false);

  return (
    <>
      <Button variant="destructive" onClick={() => setOpen(true)}>
        제출 취소
      </Button>
      <ConfirmDialog
        open={open}
        onOpenChange={setOpen}
        title="제출을 취소하시겠습니까?"
        description="취소하면 현재 채점 대기열에서 빠지고, 학생에게 다시 제출 요청을 보내야 합니다."
        tone="destructive"
        confirmLabel="제출 취소"
        cancelLabel="돌아가기"
        onConfirm={async () => {
          await new Promise((resolve) => setTimeout(resolve, 1000));
        }}
      />
    </>
  );
}

외부 loading

loading prop으로 닫기 방지
코드 보기tsx
import { useState } from "react";
import { Button, ConfirmDialog } from "@olundot/ui";

export function ConfirmDialogLoading() {
  const [open, setOpen] = useState(false);
  const [loading, setLoading] = useState(false);

  async function handleConfirm() {
    setLoading(true);
    await new Promise((resolve) => setTimeout(resolve, 1200));
    setLoading(false);
  }

  return (
    <>
      <Button variant="outline" onClick={() => setOpen(true)}>
        재계산 실행
      </Button>
      <ConfirmDialog
        open={open}
        onOpenChange={setOpen}
        title="점수를 다시 계산할까요?"
        description="계산 중에는 창을 닫을 수 없고, 완료 후 결과가 갱신됩니다."
        confirmLabel="재계산"
        loading={loading}
        onConfirm={handleConfirm}
      />
    </>
  );
}