按鈕與切換

實體按鍵

兩層結構的實體按鍵 React 元件:面板浮在底座上,滑過微沉 2px、按下沉到底,實心色塊做出深度,不靠陰影模糊。

像實體鍵盤一樣有行程的按鈕。<button> 內有兩層:底座往下偏移一個行程深度,面板浮在上方;滑鼠滑過時面板微沉 2px,按下(或用鍵盤按住空白鍵/Enter)時沉到與底座齊平。深度完全由實心色塊構成,沒有模糊陰影也沒有 spring,節奏與色彩都外露成 --wb-tactile-* 變數。支援三種尺寸、深淺兩種配色、左側圖示,以及寬度不跳動的載入狀態。

把這個效果裝進你的專案

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

npx webberui@latest add tactile-button

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

Playground

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

6
150
編輯中的呼叫預設屬性
<TactileButton/>

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

安裝

npx webberui@latest add https://webberui.com/r/tactile-button.json

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

使用

import { Download } from "lucide-react";
import { TactileButton } from "@/components/ui/tactile-button";

<TactileButton onClick={() => console.log("已儲存")}>儲存</TactileButton>

<TactileButton variant="light" icon={<Download />} depth={8}>
  下載報表
</TactileButton>

<TactileButton size="lg" loading>
  付款中
</TactileButton>

Props

Prop型別預設值說明
childrenReact.ReactNode—按鍵文字或內容
size"sm" | "md" | "lg""md"尺寸:sm 高 36px、md 高 44px、lg 高 52px;行程深度不隨尺寸改變
variant"dark" | "light""dark"配色:dark 深色面板、light 淺色面板;深色模式下各自改用對應的一組色票
depthnumber6行程深度(px):面板浮在底座上方的高度,按到底時剛好與底座齊平
iconReact.ReactNode—文字左側的圖示,會依尺寸自動設為 16/18/20px
loadingbooleanfalse載入中:面板內容換成小 spinner、設定 aria-busy 並暫停點擊,寬度不變
disabledbooleanfalse停用:45% 不透明、游標改為禁止,且不會有任何位移
refReact.Ref<HTMLButtonElement>—轉發到原生 <button> 的 ref
classNamestring—併入最外層 <button> 的 class

其餘原生 <button> 屬性(onClick、type、aria-*、form 等)全部透傳,type 預設為 "button"。

CSS 變數

欄位型別預設值說明
--wb-tactile-facecolor依 variant面板顏色(dark:neutral-700;light:neutral-100)
--wb-tactile-basecolor依 variant底座顏色(dark:neutral-900;light:neutral-300)
--wb-tactile-highlightcolor依 variant面板頂緣 1px 內高光(dark:neutral-600;light:white)
--wb-tactile-contentcolor依 variant文字與圖示顏色(dark:neutral-100;light:neutral-900)
--wb-tactile-durationtime150ms面板位移的時長
--wb-tactile-easeeasingcubic-bezier(0.23,1,0.32,1)面板位移的緩動曲線

細節

  • 按鈕本身以 padding-bottom 保留整段行程,面板下沉時外框尺寸不變,周圍版面不會跳動。
  • 滑過下沉只在 (hover: hover) and (pointer: fine) 的裝置生效,觸控螢幕不會在點擊後卡在半沉狀態。
  • 三種位移狀態(滑過、按下、鍵盤按住)的選擇器互斥,只改一個 --tactile-y 變數,不依賴 CSS 先後順序。
  • 色彩一律讀 var(--wb-tactile-*, 配色預設值):在任何祖先元素設定 --wb-tactile-* 即可整站換色;深色模式下 dark 配色反轉成淺色面板,light 配色改成深色面板。
  • 載入狀態用 grid 疊層:原本的文字隱形占位,spinner 疊在同一格,寬度維持不變;載入中不使用原生 disabled,焦點不會因此跳走。

可及性

  • 使用原生 <button>,type 預設 "button",空白鍵與 Enter 都能觸發
  • focus-visible 時整顆按鍵(含底座)外圍顯示 2px 外框,與面板位移互不干擾
  • 鍵盤按住空白鍵或 Enter 時以 data-pressed 呈現與滑鼠按下相同的下沉,不依賴瀏覽器對鍵盤 :active 的支援
  • 載入中設定 aria-busy 與 aria-disabled,原本的文字仍留在 DOM 中作為可及名稱;spinner 對輔助科技隱藏
  • 只放圖示的按鍵請傳 aria-label;icon 外層已設 aria-hidden
  • 使用者系統開啟「減少動態效果」時,面板不再位移,按下時改為即時降低亮度(brightness 95%)