按鈕與切換

滑動解鎖

拖曳滑塊到底才觸發的確認控制,防誤觸。

拖曳滑塊到底才觸發確認的防誤觸控制,適合付款、刪除等不可逆操作。未過門檻放手會 spring 回彈,成功時滑塊吸附終點並打勾,軌道提示文字帶 shimmer 高光掃過,並支援鍵盤方向鍵推進。

把這個效果裝進你的專案

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

npx webberui@latest add slide-to-unlock

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

Slide to Unlock 是用 React、Motion 與 Tailwind CSS 做的滑動確認(滑動解鎖、slide to confirm)元件:使用者必須把滑塊拖過門檻才會呼叫 onConfirm,常用來擋住誤觸的付款與刪除操作。

Playground

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

0.9
2000
編輯中的呼叫預設屬性
<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型別預設值說明
labelstring"滑動解鎖"軌道中央的 shimmer 提示文字
successLabelstring"已確認"解鎖成功後顯示的文字
thresholdnumber0.9觸發確認所需的拖曳比例(0 ~ 1),未達放手回彈
onConfirm() => void—滑塊到達終點時呼叫(每次解鎖僅觸發一次)
resetDelaynumber0成功後自動重置的延遲(毫秒),0 表示維持解鎖狀態
disabledbooleanfalse停用互動(拖曳與鍵盤皆無效)
classNamestring—合併到最外層軌道

可及性

  • 滑塊為 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 的話,可以在安裝區的「手動」分頁照步驟複製原始碼。