按鈕與切換

彈簧開關

以彈簧位移的 React 開關元件:thumb 可直接拖曳切換,可在 thumb 內放 icon 交叉淡接,另有壓下態的切換鈕變體,支援原生表單送出。

設定頁最常見的開關。點擊、按 Space/Enter,或直接抓著 thumb 拖到另一側都能切換;thumb 以彈簧位移,拖曳時 track 底色依進度漸變,放開時越過一半就切到對側、否則彈回原位。thumb 內可放開/關兩個 icon,切換時旋轉淡入交接。variant="button" 會變成壓下態的切換鈕(aria-pressed),適合文字工具列這類「按下=開啟」的場景。狀態支援受控/非受控雙模式,給 name 即可隨原生表單送出。

把這個效果裝進你的專案

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

npx webberui@latest add switch

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

Playground

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

500
30
編輯中的呼叫預設屬性
<Switch/>

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

安裝

npx webberui@latest add https://webberui.com/r/switch.json

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

使用

import { Moon, Sun } from "lucide-react";
import { Switch } from "@/components/ui/switch";

const [dark, setDark] = React.useState(false);

<Switch
  label="深色模式"
  description="跟隨你的偏好切換介面配色"
  checked={dark}
  onCheckedChange={setDark}
  icons={{ on: <Moon />, off: <Sun /> }}
/>

// 壓下態切換鈕
<Switch variant="button" label="粗體" defaultChecked />

// 原生表單:開啟時送出 newsletter=yes
<Switch name="newsletter" value="yes" label="訂閱電子報" />

Props

Prop型別預設值說明
checkedboolean—受控的開關狀態;未提供時由元件內部管理(非受控)
defaultCheckedbooleanfalse非受控模式的初始狀態
onCheckedChange(checked: boolean) => void—狀態變動時回呼,參數為切換後的新狀態
size"sm" | "md" | "lg""md"尺寸:track 分別為 28×16、36×20、44×24
disabledbooleanfalse停用:不可點擊、拖曳或鍵盤切換,外觀灰化
labelReactNode—標籤;switch 變體渲染為可點擊的 label,button 變體則成為按鈕文字
descriptionReactNode—補充說明,以 aria-describedby 關聯
variant"switch" | "button""switch"外觀變體:滑動開關或壓下態切換鈕
iconsSwitchIcons—thumb 內的開/關 icon,切換時交叉淡接
stiffnessnumber500thumb 彈簧剛性
dampingnumber30thumb 彈簧阻尼
namestring—原生表單欄位名稱;有提供時以 hidden input 隨表單送出
valuestring"on"開啟時隨表單送出的值
classNamestring—透傳到最外層容器

SwitchIcons

欄位型別預設值說明
onReactNode—開啟時顯示的 icon
offReactNode—關閉時顯示的 icon

細節

  • 拖曳:在 thumb 上按下後以 setPointerCapture 鎖定指標,thumb 跟隨指標並限制在 track 範圍內;放開時位置越過一半就切到對側,否則彈回原位。移動不到 3px 視為點擊;拖曳結束後會吞掉瀏覽器補發的那一次 click,避免二次切換。
  • track 的開啟色是一層疊在底色上的色塊,拖曳中依進度 0–1 調整透明度,平時以 --wb-switch-duration(預設 150ms)過渡;可在全域或外層覆寫這個變數調整節奏。
  • 深色模式下開啟的 track 是淺色,thumb 會改為深色以保持對比。
  • 開關本身不是文字輸入,Space/Enter 交給原生 <button> 處理,不會受輸入法組字影響。
  • 表單送出比照原生 checkbox:只有開啟時才會帶上 name=value,關閉時不送出。

可及性

  • switch 變體為 <button role="switch">,以 aria-checked 表示狀態;label 以 htmlFor 關聯,點擊文字也能切換
  • button 變體為 <button aria-pressed>(不是 role="switch"),適合工具列;description 在此變體以視覺隱藏文字提供給螢幕閱讀器
  • description 以 aria-describedby 關聯;thumb 與 icon 對輔助科技隱藏
  • 鍵盤:Tab 聚焦後按 Space 或 Enter 切換,聚焦時顯示 focus-visible 外框;disabled 時無法聚焦與操作
  • 使用者系統開啟「減少動態效果」時,thumb 不走彈簧而是直接到位、停用拖曳只保留點擊,icon 只淡入不旋轉,切換鈕按住時也不縮放