Đến nội dung chính

Hộp thoại xác nhận

Lần duy nhất nói rõ cái gì sắp mất, ngay trước một việc không thể hoàn lại.

Lớp phủ

Xem trước trực tiếp

Nguồn

<div class="dc-cfm-stage">
  <div class="dc-cfm" role="alertdialog" aria-modal="true" aria-labelledby="dc-cfm-t" aria-describedby="dc-cfm-d">
    <div class="dc-cfm__icon dc-cfm__icon--warn"><svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M12 4.2 2.6 20h18.8L12 4.2Z" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/><path d="M11.1 10h1.8v4.4h-1.8zM11.1 16h1.8v1.8h-1.8z" fill="currentColor"/></svg></div>
    <h2 class="dc-cfm__title" id="dc-cfm-t">저장하지 않고 나갈까요?</h2>
    <p class="dc-cfm__text" id="dc-cfm-d">작성한 내용 12줄이 사라집니다. 되돌릴 수 없습니다.</p>
    <div class="dc-cfm__acts">
      <button class="dc-cfm__btn" type="button">나가기</button>
      <button class="dc-cfm__btn dc-cfm__btn--strong" type="button">계속 작성</button>
    </div>
  </div>
</div>
.dc-cfm-stage {
  display: flex; align-items: center; justify-content: center;
  min-height: 300px; padding: var(--dc-5);
  background: var(--dc-overlay); border-radius: var(--dc-r-md);
  font-family: var(--dc-font);
}
.dc-cfm {
  width: 100%; max-width: 380px; padding: var(--dc-6);
  background: var(--dc-surface);
  border: 1px solid var(--dc-line); border-radius: var(--dc-r-lg);
  box-shadow: var(--dc-sh-3);
  text-align: center;
}
.dc-cfm__icon {
  display: grid; place-items: center; width: 44px; height: 44px;
  margin: 0 auto var(--dc-4); border-radius: var(--dc-r-full);
}
.dc-cfm__icon svg { width: 24px; height: 24px; }
.dc-cfm__icon--warn { background: var(--dc-warn-soft); color: var(--dc-warn); }
.dc-cfm__icon--danger { background: var(--dc-danger-soft); color: var(--dc-danger); }
.dc-cfm__title { margin: 0 0 var(--dc-2); font-size: 16px; font-weight: 700; line-height: 1.45; color: var(--dc-text); }
.dc-cfm__text { margin: 0; font-size: 13px; line-height: 1.7; color: var(--dc-text-sub); }
.dc-cfm__note { margin: var(--dc-3) 0 0; font-size: 12px; line-height: 1.6; color: var(--dc-text-mute); }
.dc-cfm__acts { display: flex; gap: var(--dc-2); margin-top: var(--dc-6); }
.dc-cfm__acts--stack { flex-direction: column; }
.dc-cfm__btn {
  flex: 1 1 auto; min-height: 44px; padding: 0 var(--dc-4);
  border: 1px solid var(--dc-line-field); border-radius: var(--dc-r-sm);
  background: var(--dc-surface); color: var(--dc-text);
  font-size: 14px; font-weight: 600;
  transition: background var(--dc-fast), border-color var(--dc-fast);
}
.dc-cfm__btn:hover { background: var(--dc-sunken); }
.dc-cfm__btn--strong { border-color: var(--dc-brand); background: var(--dc-brand); color: var(--dc-text-on); }
.dc-cfm__btn--strong:hover { background: var(--dc-brand-hi); border-color: var(--dc-brand-hi); }
.dc-cfm__btn--danger { border-color: var(--dc-danger); background: var(--dc-danger); color: var(--dc-text-on); }
.dc-cfm__btn--danger:hover { background: color-mix(in srgb, var(--dc-danger) 86%, var(--dc-text)); }
@media (max-width: 420px) {
  .dc-cfm { padding: var(--dc-5); }
  .dc-cfm__acts { flex-direction: column-reverse; }
}

Cách dùng

  • Ghi trên nút chính việc sẽ xảy ra — 'Xoá 3 nhà cung cấp', không phải 'OK'
  • Nói rõ mất cái gì, kèm con số
  • Việc nào hoàn lại được thì đừng hỏi — cứ làm rồi cho nút 'Hoàn lại'

Điểm cần lưu ý

  • Dùng role=alertdialog kèm aria-describedby để tiêu đề và nội dung được đọc cùng nhau
  • Đừng để nút phá huỷ là tiêu điểm mặc định — một lần Enter là xong

Tiếp theo