跳至主要内容
💬 回報這一頁

Button 按鈕

觸發一個動作。

在 Storybook 開啟

何時不要用

✅ 這樣做

導向另一個頁面 → 用連結(<a>)。需要長得像按鈕就用 asChild

🚫 不要這樣

不要用 <button onClick={() => navigate()}> 做導覽—— 使用者沒辦法中鍵開新分頁、沒辦法複製網址,而且搜尋引擎與螢幕報讀器都讀不懂。

變體

default 主要動作 · secondary 次要 · outline 外框 · ghost 淡化 · link 連結樣式 · destructive 破壞性動作

變體與尺寸

狀態

狀態表現
預設依變體
hover狀態層 6%(疊一層 currentColor,不換底色)
pressed狀態層 14%——按住的瞬間要有回饋
focus-visible2px 聚焦環 + 2px 偏移(只在鍵盤操作時出現
disabled透明度 50%、pointer-events: none,且不套狀態層
loading沒有獨立變體:設 disabled、換旋轉圖示、改文案

hover 與 pressed 由 .state-layer 這個 utility 提供,六個變體共用同一組強度。 改版前每個變體各挑一個透明度(/90/80…),可見度從 ΔE00 0.6secondary,等於沒有 hover)到 7.4default,過於刻意)差了十倍; 現在全部落在 2.6–4.5。理由與量測見互動狀態的顏色邏輯

link 變體刻意不套狀態層:它是一段文字不是一塊表面,疊上去會在字後面浮出一個色塊。 它的 hover 走底線。

為什麼沒有 loading 變體:多一個變體只會讓人猶豫該用哪個。 用既有的 disabled + 圖示 + 文案,語意更清楚(「正在處理,現在不能按」)。 這是載入中三種手段的第三種—— 內容區域的載入(骨架、就地變暗)是另外兩種,不要拿按鈕的做法去蓋整個畫面。

一顆畫面上只有一顆主要按鈕

default 變體是「這個畫面最主要的那件事」。兩顆並排的深色按鈕等於沒有主次。

無障礙

  • 圖示按鈕必須aria-label
  • 破壞性動作建議搭配 Dialog 二次確認
  • 觸控裝置的按鈕至少 44px(size="default" 已達 40px,密集區域加 tap-target

取用

npx shadcn@latest add https://kielchang.github.io/dooping-design-book/r/button.json