覆蓋層與回饋

確認對話框

需要明確回應的確認對話框:遮罩淡入、面板微縮放進場,焦點鎖定與捲動鎖定,危險操作可改為長按填滿才觸發。

刪除、離開、覆寫這類動作需要使用者明確回應的確認對話框。開啟時遮罩淡入、面板從 95% 微縮放進場(預設 100ms),焦點鎖在面板內、背景加上 inert 並鎖住頁面捲動;關閉後焦點回到觸發元素。variant 決定語意與關閉方式:alert 只能按鈕或 Escape 關閉,plain 點遮罩也能關,destructive 換成紅色主鈕與警示圖示。危險操作可以把 confirmMode 設為 hold,主鈕要按住到填滿才會觸發,避免手滑。onConfirm 回傳 Promise 時主鈕顯示載入中,成功才關閉、失敗保持開啟。

把這個效果裝進你的專案

在專案資料夾執行指令,CLI 會加入原始碼與依賴套件,再依下方使用範例引用元件。

npx webberui@latest add confirm-dialog

還沒有專案,或安裝遇到問題?看快速開始 →

Playground

即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。

100
1600
編輯中的呼叫預設屬性
<ConfirmDialog/>

完整範例包含預覽的排版與資料。先安裝元件,再把範例檔貼入你的專案。

安裝

npx webberui@latest add https://webberui.com/r/confirm-dialog.json

或在 components.json 設定 registries 後,改用 @webberui/confirm-dialog 安裝。

使用

import { ConfirmDialog } from "@/components/ui/confirm-dialog";

<ConfirmDialog
  trigger={<button type="button">刪除專案</button>}
  variant="destructive"
  confirmMode="hold"
  title="刪除這個專案?"
  description="刪除後 30 天內可從封存區還原,之後將永久移除。"
  confirmLabel="刪除專案"
  onConfirm={async () => {
    // 回傳 Promise:成功後關閉,失敗保持開啟
    await deleteProject();
  }}
/>

也可以不給 trigger,改用 open/onOpenChange 從外部控制;關閉時焦點會還給開啟當下的焦點元素。

Props

Prop型別預設值說明
openboolean—受控的開啟狀態;不傳則由元件內部管理
defaultOpenbooleanfalse非受控模式的初始開啟狀態
onOpenChange(open: boolean) => void—開啟狀態變更時的回呼
triggerReactNode—觸發元素;元素會被接上 onClick,字串會包成預設按鈕;關閉後焦點回到它
titleReactNode—對話框標題(aria-labelledby 指向它)
descriptionReactNode—標題下方的說明(aria-describedby 指向它)
childrenReactNode—說明下方的自訂內容,例如確認用的輸入框
cancelLabelstring"取消"取消鈕文字
confirmLabelstring"確認"確認鈕文字
onConfirm() => void | Promise<void>—確認時呼叫;回傳 Promise 時顯示載入中,resolve 後關閉、reject 時保持開啟
onCancel() => void—按取消鈕、Escape 或(plain)點遮罩時呼叫
variant"plain" | "alert" | "destructive""alert"對話框語意與外觀
confirmMode"click" | "hold""click"hold 時主鈕需按住到填滿才確認
holdDurationnumber1600hold 模式需按住的時長(毫秒)
confirmDisabledbooleanfalse停用確認鈕
hideCancelbooleanfalse隱藏取消鈕,僅 plain 有效
durationnumber100遮罩與面板進退場時長(毫秒),同時寫入 --wb-confirm-dialog-duration
classNamestring—追加到對話框面板

另外具名匯出型別 ConfirmDialogVariant 與 ConfirmDialogConfirmMode。

細節

  • 三種變體:alert 與 destructive 使用 role="alertdialog",點遮罩不會關閉,只能按鈕或 Escape;plain 使用 role="dialog",點遮罩即取消。
  • 開啟時的初始焦點:alert/destructive 落在取消鈕,避免連按 Enter 誤觸危險操作;plain 落在面板內第一個可聚焦元素。
  • 捲動鎖定會補上捲軸寬度的 padding-right,背景版面不會因捲軸消失而跳動;關閉時還原原本的樣式。
  • hold 模式:按下(滑鼠、觸控、Space 或 Enter)時填充條以等速由左到右填滿,放開或移出即在 200ms 內退回;超過 85% 時按鈕輕微震顫;填滿才呼叫 onConfirm。
  • 非同步確認期間取消鈕與 Escape 都會暫時失效,避免結果回來時對話框已關閉。
  • 時長變數:按鈕的顏色過渡讀取 --wb-confirm-dialog-duration,可在主題層統一覆寫。

可及性

  • 面板設定 aria-modal="true",aria-labelledby/aria-describedby 分別指向標題與說明
  • Tab/Shift+Tab 在面板內循環,背景節點加上 inert,螢幕閱讀器與鍵盤都進不去
  • Escape 關閉(IME 組字中按 Escape 只會取消組字);關閉後焦點回到觸發元素或開啟前的焦點元素
  • 非同步確認期間主鈕設定 aria-busy;hold 模式主鈕以 aria-describedby 連到「按住以確認」說明
  • 使用者系統開啟「減少動態效果」時,面板只淡入不縮放;hold 填充改為原地加深並以文字倒數「按住 2 秒…1 秒…」呈現,不震顫