본문으로 건너뛰기
Dot Design System
v0.3.1

ConfirmActionDialog

대상, 영향, 복구 가능성을 포함해 중요한 행동을 확인합니다.

목적

ConfirmActionDialog는 사용자가 실행 결과를 다시 확인해야 하는 행동을 보호한다. 삭제처럼 되돌릴 수 없는 행동뿐 아니라, 현재 작업을 잃거나 운영 상태가 바뀌는 행동에도 사용할 수 있다. 대상, 결과, 다음 행동을 한 화면에서 설명하며 브라우저 기본 확인창을 대신한다.

선택 기준

  • 실행 즉시 데이터, 권한, 공개 상태 또는 진행 중인 작업이 바뀌면 사용한다.
  • 사용자가 이미 같은 내용을 명시적으로 확인한 직후에는 반복해서 열지 않는다.
  • 단순 성공 알림은 toast나 inline feedback을 사용한다.
  • 사용자의 선택 없이 알려주기만 하면 되는 내용은 일반 Dialog 또는 페이지 안의 안내를 검토한다.
  • 파괴 행동이 아니면 tone="default"를 유지한다.

구조

  1. title: 사용자가 결정해야 하는 행동을 짧게 말한다.
  2. description: 대상, 영향, 되돌릴 수 있는지를 설명한다.
  3. children: 추가 경고, 대상 요약, 입력 확인처럼 꼭 필요한 내용을 넣는다.
  4. 취소 버튼: 현재 상태를 유지한다.
  5. 확인 버튼: 실행 결과가 드러나는 레이블을 사용한다.

변형과 크기

  • tone="default": 저장하지 않고 이동, 상태 변경처럼 파괴가 아닌 확인에 사용한다.
  • tone="destructive": 삭제, 연결 해제, 영구 폐기처럼 복구가 어렵거나 불가능한 행동에만 사용한다.
  • 콘텐츠 영역은 화면 높이의 90% 안에서 스크롤된다. 임의의 크기 prop은 제공하지 않는다.
  • 확인·취소 버튼은 최소 40px 높이를 유지한다.

상태와 동작

  • openonOpenChange를 함께 사용해 표시 상태를 소비 제품이 소유한다.
  • 확인 버튼은 클릭만으로 자동 닫히지 않는다. onConfirm에서 작업을 시작하고, 성공한 뒤 onOpenChange(false)를 호출한다.
  • isPending 동안 두 버튼이 비활성화되고 외부 동작으로 닫히지 않는다.
  • confirmDisabled는 확인 조건을 충족하지 못했을 때 사용한다. 다이얼로그 안에서 이유를 함께 설명한다.
  • pendingLabel이 없으면 처리 중에도 confirmLabel을 유지한다.
  • 작업 실패 시 다이얼로그를 유지하고 children 또는 인접한 상태 영역에 복구 방법을 보여준다.

콘텐츠

  • 제목은 이 연결을 해제할까요?처럼 결정 대상을 포함한다.
  • 설명에는 사용자가 잃는 것, 유지되는 것, 복구 방법을 우선순위대로 쓴다.
  • 확인 레이블은 해제, 확인보다 연결 해제, 초안 없이 나가기처럼 결과를 말한다.
  • 처리 중 레이블은 연결 해제 중…처럼 현재 작업을 유지한다.
  • 위험을 과장하거나 사용자를 탓하지 않는다.

접근성

  • 제목과 설명은 alert dialog의 접근 가능한 이름과 설명으로 연결된다.
  • aria-busy가 확인 버튼의 처리 중 상태를 전달한다.
  • 추가 경고가 확인 판단에 필수라면 해당 요소의 ID를 confirmAriaDescribedBy에 전달한다.
  • returnFocusRef를 제공하면 닫힌 뒤 연결된 요소로 초점이 돌아간다. 목록에서 행이 사라지는 경우처럼 trigger가 제거될 수 있으면 안전하게 남아 있는 요소를 지정한다.
  • 색상만으로 위험을 전달하지 말고 제목과 설명에 결과를 명시한다.

좁은 화면과 긴 콘텐츠

  • 버튼은 좁은 화면에서 세로 흐름이 될 수 있으므로 레이블만으로 각 행동을 구분할 수 있어야 한다.
  • 긴 설명을 넣을 수 있지만 정책 전문이나 대량 데이터를 다이얼로그에 넣지 않는다. 상세 검토가 필요하면 별도 페이지나 sheet로 이동한다.
  • 긴 대상명은 줄바꿈을 허용하고 중요한 식별자를 문장 앞부분에 둔다.
  • 스크롤이 생겨도 제목, 설명, 행동의 의미가 유지되어야 한다.

공개 API

속성타입기본값설명
openboolean필수다이얼로그 표시 여부
titlestring필수결정 제목
descriptionstring필수결과와 영향 설명
confirmLabelstring필수확인 행동 레이블
cancelLabelstring'취소'현재 상태를 유지하는 행동 레이블
pendingLabelstringconfirmLabel처리 중 레이블
tone'default' | 'destructive''default'확인 행동의 의미 톤
isPendingbooleanfalse비동기 작업 진행 여부
confirmDisabledbooleanfalse확인 행동 비활성 여부
confirmAriaDescribedBystring없음확인 버튼에 추가로 연결할 설명 ID
returnFocusRefRefObject<HTMLElement | null>없음닫힌 뒤 초점을 돌려보낼 요소
childrenReactNode없음추가 경고 또는 대상 요약
onOpenChange(open: boolean) => void필수표시 상태 변경 요청
onConfirm() => void필수확인 행동 실행

예제

사용 코드 · TSX
import { useRef, useState } from 'react';
import { Button, ConfirmActionDialog } from '@classum/dot-design-system/ui';

export function DisconnectAction({ onDisconnect }: { onDisconnect: () => Promise<void> }) {
  const triggerRef = useRef<HTMLButtonElement>(null);
  const [open, setOpen] = useState(false);
  const [pending, setPending] = useState(false);

  async function disconnect() {
    setPending(true);
    try {
      await onDisconnect();
      setOpen(false);
    } finally {
      setPending(false);
    }
  }

  return (
    <>
      <Button ref={triggerRef} variant="outline" onClick={() => setOpen(true)}>
        워크스페이스 연결 해제
      </Button>
      <ConfirmActionDialog
        open={open}
        title="워크스페이스 연결을 해제할까요?"
        description="자동 동기화가 중단돼요. 저장된 기록은 삭제되지 않아요."
        confirmLabel="연결 해제"
        pendingLabel="연결 해제 중…"
        tone="destructive"
        isPending={pending}
        returnFocusRef={triggerRef}
        onOpenChange={setOpen}
        onConfirm={disconnect}
      />
    </>
  );
}

피해야 할 사용

  • 성공 사실을 알리기 위해 확인 버튼 하나만 둔 다이얼로그
  • 모든 저장과 이동에 습관적으로 확인을 요구하는 흐름
  • 파괴 행동이 아닌데 destructive tone을 사용하는 경우
  • isPending 없이 중복 실행을 허용하는 비동기 확인
  • 실패했는데 다이얼로그를 먼저 닫아 작업 맥락을 잃게 하는 처리
  • 확인, 진행처럼 결과를 예측할 수 없는 레이블

관련 항목