按鈕與切換
雙態文字開關
兩態文字開關(例如「詢問|自動」),玻璃質感把手以彈簧滑動,文字隨把手位置交叉淡接,適合切換助理或系統的運作模式。
只有兩個選項的文字開關:膠囊 track 兩側各放一個標籤,一顆半透明玻璃把手蓋住目前選中的那一側。點擊、方向鍵或直接拖曳把手都能切換,把手以彈簧滑過去、到位時有一下果凍形變;兩側文字的顏色與透明度跟著把手位置連續插值,而不是選中瞬間才換色。把手寬度等於它蓋住那側的標籤寬,拖曳途中在兩側寬度之間平滑過渡。適合「詢問|自動」這類運作模式、「月繳|年繳」或「預覽|編輯」。
把這個效果裝進你的專案
在專案資料夾執行指令,CLI 會加入原始碼與依賴套件,再依下方使用範例引用元件。
npx webberui@latest add labeled-mode-switchPlayground
即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。
500
32
編輯中的呼叫預設屬性
<LabeledModeSwitch/>
完整範例包含預覽的排版與資料。先安裝元件,再把範例檔貼入你的專案。
安裝
npx webberui@latest add https://webberui.com/r/labeled-mode-switch.json或在 components.json 設定 registries 後,改用 @webberui/labeled-mode-switch 安裝。
使用
import { MessageCircleQuestion, Zap } from "lucide-react";
import { LabeledModeSwitch } from "@/components/ui/labeled-mode-switch";
const [mode, setMode] = React.useState("ask");
<LabeledModeSwitch
aria-label="助理執行模式"
value={mode}
onValueChange={setMode}
options={[
{ value: "ask", label: "詢問", icon: <MessageCircleQuestion /> },
{ value: "auto", label: "自動", icon: <Zap /> },
]}
/>Props
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
options | [LabeledModeSwitchOption, LabeledModeSwitchOption] | 「詢問|自動」 | 固定兩個選項:[左側, 右側] |
value | string | — | 受控模式的當前值;提供後由外部完全控制 |
defaultValue | string | 左側選項的 value | 非受控模式的初始值 |
onValueChange | (value: string) => void | — | 選中值變更時的回呼 |
size | "sm" | "md" | "lg" | "md" | 尺寸 |
draggable | boolean | true | 是否允許拖曳把手切換(點擊與鍵盤永遠可用) |
stiffness | number | 500 | 把手彈簧剛度,越大越快到位 |
damping | number | 32 | 把手彈簧阻尼,越大回彈越少 |
disabled | boolean | false | 停用整個開關 |
aria-label | string | — | 提供給輔助科技的群組名稱 |
className | string | — | 透傳到最外層 track |
LabeledModeSwitchOption
| 欄位 | 型別 | 預設值 | 說明 |
|---|---|---|---|
value | string | — | 選項的唯一值 |
label | string | — | 顯示文字 |
icon | ReactNode | — | 選填的前置圖示,顏色跟隨文字 |
CSS 變數
| 變數 | 預設值 | 說明 |
|---|---|---|
--wb-mode-switch-glass | rgb(255 255 255 / 0.55)(深色模式 0.12) | 玻璃把手的底色 |
--wb-mode-switch-blur | 10px | 把手的 backdrop 模糊半徑(另加 saturate(1.6)) |
--wb-mode-switch-accent | transparent | 疊在把手上的染色層,可給把手上品牌色 |
細節
- 把手寬度:掛載後量測兩側標籤的位置與寬度(
ResizeObserver追蹤字型載入與文字變動),把手寬度依位置在兩側寬度間插值,所以長短不一的標籤也能剛好蓋住。量測完成前把手先隱藏,伺服器渲染的首屏不會出現錯位。 - 拖曳:從把手所在那側按下即可水平拖曳,限制在 track 內(
dragElastic0.1);放手時依位置是否過半決定狀態,沒過半就彈回原位。拖曳只是增強,點擊與鍵盤完全等價。 - 點擊:點另一側選它;點目前選中那側則切換到另一側。
- 動態:位移使用 spring(預設
stiffness500、damping32),切換瞬間把手scaleX1 → 1.08 → 1 做一次果凍形變。 - 文字交叉淡接:每個標籤由 muted 與前景兩層疊成,前景層透明度隨把手位置連續變化,標籤整體透明度在 0.55 與 1 之間插值;圖示用
currentColor,跟著一起換色。
可及性
- 選用
role="radiogroup"包兩個role="radio"(aria-checked)而不是role="switch":兩側都有各自的語意標籤,radio 能讓螢幕閱讀器直接念出「詢問,已選取」這類完整資訊;請以aria-label為群組命名 - roving tabindex:Tab 只停在選中項;左右方向鍵分別選左側/右側,上下方向鍵與空白鍵切換到另一側,焦點跟著移動
- focus-visible 時整條 track 顯示 ring
disabled時兩顆按鈕都停用,拖曳也關閉- 使用者系統開啟「減少動態效果」時,把手直接跳到新位置(無彈簧、無果凍形變),文字直接換色