滑動解鎖
拖曳滑塊到底才觸發的確認控制,防誤觸。
拖曳滑塊到底才觸發確認的防誤觸控制,適合付款、刪除等不可逆操作。未過門檻放手會 spring 回彈,成功時滑塊吸附終點並打勾,軌道提示文字帶 shimmer 高光掃過,並支援鍵盤方向鍵推進。
把這個效果裝進你的專案
在專案資料夾執行指令,CLI 會加入原始碼與依賴套件,再依下方使用範例引用元件。
npx webberui@latest add slide-to-unlockSlide to Unlock 是用 React、Motion 與 Tailwind CSS 做的滑動確認(滑動解鎖、slide to confirm)元件:使用者必須把滑塊拖過門檻才會呼叫 onConfirm,常用來擋住誤觸的付款與刪除操作。
Playground
即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。
<SlideToUnlock/>
完整範例包含預覽的排版與資料。先安裝元件,再把範例檔貼入你的專案。
適用情境
- 行動版結帳頁的「滑動以付款」確認
- 刪除帳號、清空資料等不可逆操作的最後一步
- 外送、叫車 App 的「滑動以完成訂單」或「確認抵達」
- 智慧家居控制介面中開門、解除警報這類需要刻意動作的指令
- 不適合:送出後需要顯示載入中、成功或失敗狀態的非同步請求,請改用 Stateful Button;桌面版想用長按確認的話可以看 Hold to Confirm
安裝
npx webberui@latest add https://webberui.com/r/slide-to-unlock.json或在 components.json 設定 registries 後,改用 @webberui/slide-to-unlock 安裝。
使用
import { SlideToUnlock } from "@/components/ui/slide-to-unlock";
<SlideToUnlock
label="滑動以確認付款"
successLabel="付款已確認"
onConfirm={() => submitPayment()}
/>範例
可重複觸發的確認
resetDelay 設為大於 0 時,解鎖後會在指定毫秒數自動歸位,適合同一頁面要多次確認的情境。
<SlideToUnlock
label="滑動以打卡"
successLabel="打卡成功"
resetDelay={2000}
onConfirm={() => recordCheckIn()}
/>勾選同意後才能滑動
用 disabled 綁定表單狀態,停用時拖曳與鍵盤操作都不會生效。
"use client";
import * as React from "react";
import { SlideToUnlock } from "@/components/ui/slide-to-unlock";
export function DeleteAccount() {
const [agreed, setAgreed] = React.useState(false);
return (
<div className="space-y-4">
<label className="flex items-center gap-2 text-sm">
<input
type="checkbox"
checked={agreed}
onChange={(e) => setAgreed(e.target.checked)}
/>
我了解刪除後資料無法復原
</label>
<SlideToUnlock
label="滑動以刪除帳號"
successLabel="已送出刪除申請"
disabled={!agreed}
onConfirm={() => deleteAccount()}
/>
</div>
);
}調整門檻與寬度
軌道預設填滿容器寬度,可用 className 限制最大寬度;threshold 越接近 1,越需要拖到底才算數。
<SlideToUnlock
className="mx-auto max-w-xs"
threshold={0.95}
label="滑動以轉帳"
successLabel="轉帳已送出"
onConfirm={() => submitTransfer()}
/>Props
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
label | string | "滑動解鎖" | 軌道中央的 shimmer 提示文字 |
successLabel | string | "已確認" | 解鎖成功後顯示的文字 |
threshold | number | 0.9 | 觸發確認所需的拖曳比例(0 ~ 1),未達放手回彈 |
onConfirm | () => void | — | 滑塊到達終點時呼叫(每次解鎖僅觸發一次) |
resetDelay | number | 0 | 成功後自動重置的延遲(毫秒),0 表示維持解鎖狀態 |
disabled | boolean | false | 停用互動(拖曳與鍵盤皆無效) |
className | string | — | 合併到最外層軌道 |
可及性
- 滑塊為
role="slider"的按鈕,以aria-valuenow/aria-valuetext即時回報進度百分比 - 完整鍵盤支援:
→/↑推進、←/↓後退(每次 10%)、End直接解鎖、Home歸零 - 解鎖成功透過
aria-live="polite"播報成功文字 - 使用者系統開啟「減少動態效果」時,關閉 shimmer 掃光,回彈與吸附改為近乎即時的定位
常見問題
可以在 Next.js App Router 使用嗎?
可以。元件檔案開頭已有 "use client",在 Server Component 頁面中照常 import 即可;onConfirm 這類函式 props 要從 client component 傳入。
onConfirm 會被呼叫幾次?
每次解鎖只呼叫一次。若 resetDelay 為 0(預設),滑塊會停在解鎖狀態,不會再次觸發;設定 resetDelay 後,歸位才能再滑一次。
鍵盤使用者能操作嗎?
可以。滑塊是 role="slider" 的按鈕,方向鍵每次推進或後退 10%,End 直接解鎖、Home 歸零;推進到 threshold 以上即視為確認。
寬度改變時會跑位嗎?
不會。元件用 ResizeObserver 量測軌道寬度並更新可拖曳範圍,已解鎖時也會重新貼齊終點。
需要哪些依賴?
motion、lucide-react、clsx 與 tailwind-merge。不想用 CLI 的話,可以在安裝區的「手動」分頁照步驟複製原始碼。