輸入元件

開關變滑桿

開關與滑桿共用同一顆把手的 React 元件:開啟後把手跳上垂直或水平滑桿可拖曳調整數值,關閉時把手跳回開關,適合「啟用後再調強度」的設定。

「先啟用、再調強度」的設定,用一顆把手就交代完。關閉時把手待在開關裡;按下開關,滑桿軌道展開,把手以彈簧沿路飛過去、飛行中略微放大像跳上去一樣,落在 min 後再一路「數到」目前數值。開啟後可直接拖曳把手或點軌道調整,拖曳中把手旁出現逐位滾動的數值氣泡;再按一次開關,把手先飛回,軌道才收起。開關狀態與數值各自支援受控/非受控雙模式,滑桿可選垂直或水平。

把這個效果裝進你的專案

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

npx webberui@latest add switch-to-slider-morph

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

Playground

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

500
28
100
編輯中的呼叫預設屬性
<SwitchToSliderMorph/>

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

安裝

npx webberui@latest add https://webberui.com/r/switch-to-slider-morph.json

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

使用

import { SwitchToSliderMorph } from "@/components/ui/switch-to-slider-morph";

const [on, setOn] = React.useState(false);
const [level, setLevel] = React.useState(72);

<SwitchToSliderMorph
  label="專注模式"
  enabled={on}
  onEnabledChange={setOn}
  value={level}
  onValueChange={setLevel}
  valueLabel={(v) => `降噪 ${v}%`}
/>

Props

Prop型別預設值說明
enabledboolean—受控的開關狀態;未提供時由元件內部管理(非受控)
defaultEnabledbooleanfalse非受控模式的初始開關狀態
onEnabledChange(enabled: boolean) => void—開關狀態變動時回呼
valuenumber—受控的滑桿數值;未提供時由元件內部管理(非受控)
defaultValuenumbermin非受控模式的初始數值
onValueChange(value: number) => void—數值變動時回呼(已依 step 對齊並夾在 min–max 之間)
minnumber0最小值
maxnumber100最大值
stepnumber1數值間距
orientation"vertical" | "horizontal""vertical"滑桿方向
lengthnumber160滑桿軌道長度(px)
labelstring"啟用"標籤文字,同時作為開關與滑桿的無障礙名稱
valueLabel(value: number) => string(v) => `${v}%`數值顯示格式,也用於 aria-valuetext
countUpbooleantrue開啟時把手先落在 min,再「數到」目前數值
stiffnessnumber500把手飛行彈簧的剛性
dampingnumber28把手飛行彈簧的阻尼
disabledbooleanfalse停用開關與滑桿
classNamestring—透傳到最外層容器

細節

  • 共享把手:開關裡與滑桿上的把手是同一個 motion layoutId(包在 LayoutGroup 內),切換時由彈簧帶著從舊位置飛到新位置;layout 動畫本身走直線,飛行中段額外做 1 → 1.2 → 1 的縮放,看起來像「跳」過去。
  • 滑桿軌道用 clip-path 展開而不是真的改高度——把手飛行的落點在 render 當下量測,軌道尺寸若還是 0 會飛錯地方。關閉時軌道延後約 200ms 才收,讓把手先飛回開關。
  • 拖曳改的是把手的 transform 位移,不會觸發 layout 動畫,所以跟手不延遲;用 setPointerCapture 確保拖出軌道外仍持續追蹤,點軌道任一處會直接跳到該值。
  • 計數只發生在「開啟那一刻」且數值大於 min 時;拖曳或按鍵會立即中止計數。
  • CSS 變數:--wb-knob-slider-accent(預設 #3b82f6,開關與 fill 顏色)、--wb-knob-slider-expand(預設 220ms,軌道展開時長)、--wb-knob-slider-count(預設 600ms,計數時長)。

可及性

  • 開關是 role="switch" 的按鈕並帶 aria-checked;滑桿把手是 role="slider",帶 aria-valuenow/aria-valuemin/aria-valuemax/aria-orientation,aria-valuetext 使用 valueLabel 的輸出
  • 兩者都以 aria-labelledby 指向 label;關閉時滑桿軌道對輔助科技隱藏
  • 鍵盤:方向鍵 ±step、PageUp/PageDown ±10 個 step、Home/End 跳到 min/max;開關與把手都有 focus-visible 外框
  • 用開關開啟後焦點移到滑桿把手,關閉後回到開關;受控值由外部改變時不搶焦點
  • 數值氣泡與標籤旁的讀數只是視覺呈現(aria-hidden),語意由 aria-valuetext 提供
  • 使用者系統開啟「減少動態效果」時,把手不跳、不計數,直接在新位置以 120ms 淡入,軌道改為淡入淡出