Design SystemComponentsButton

Button

Installation

import { Button } from "@olab/components";

Overview

膠囊形按鈕,三種尺寸(sm 28px / md 32px / lg 40px)、八種 skin。skin 依「這顆按鈕代表什麼」選:品牌主要動作、中性次要動作、外框,以及 YES / NO 與主隊 / 客隊 / 和局五個市場顏色。

每個 skin 都有 hover、按下、loading、disabled;除了 brand 以外的 skin 另有「已選取」狀態,用在一排選項中標出目前選的那一個。

Interactive Demo

PICK SKIN / SIZE / STATE — the button below is the real component

hover 與按住滑鼠就能看到真實的 hover / pressed。brand 沒有定義 selected。

State Matrix

ONE MATRIX — skin + state(size 一律固定 md,尺寸見下方 Spec),每格標注實際套用的 color / font token

real = 由真實 prop 或真實互動觸發(loading / disabled / active;default 排的按鈕可直接按住滑鼠測試 pressed,非凍結畫面)。 sim = 無法在靜態頁面被滑鼠 / 鍵盤真的 觸發(hover / pressed,以及 selected+hover / selected+pressed 這兩個 brightness filter 疊加態——雖然 component 上是真的 CSS 偽類,但這裡改用「把該 state 的 token 直接強制套用」來凍結視覺呈現 該狀態長什麼樣,一眼可見、不用真的滑過去/按住,非真實互動)。 N/A = 該 skin 未定義對應 token(如 實)。

每格每行 = 色票(隨模式即時解析)+ 角色(bg / text / border…)+ 實際套用的 Tier 2 semantic token;下方灰色小字 = 它在 style.css 解析到的 Tier 1 primitive 錨點——dark / light 指向不同階時拆成兩行, 以 = dark(預設模式)、 = light 標示;單行無 icon = 兩模式同階。 tint / team bg 系在 style.css 內經過 legacy alias 中繼(green-1-06 / blue-06 / sport-*-bg),此處只標 alias 鏈末端的 ramp 階。white / black 是依模式反轉的 role token,所以兩模式的 neutral 階剛好對調。

Token 資料來源:packages/components/src/components/Button/index.tsx 的 skinClasses / sizeClasses / loadingClasses,人工同步維護——@olab/components 解析到packages/components/dist/(一份 build 產物),src 改動需要重新在該 package 跑 npm run build 才會反映到這頁,不是即時的, 所以這裡仍用手動維護的表格而非直接 import skinClasses。

skindefaulthoverpressedselectedselected+hoverselected+pressedloadingdisabled
brand
bgbrand-mainbrand-600
textbrand-contrastneutral-950neutral-0
real
hover / 按住 可試
bgbrand-500Tier 1 直接引用(brand ramp 本體)
bgbrand-pressedbrand-700
無定義
無定義
無定義
iconwhiteneutral-0neutral-950
real
bgdisabled-bgneutral-700neutral-100
textgray-3neutral-400neutral-600
real
secondary
bgsecondaryneutral-850neutral-50
textprimaryneutral-0neutral-950
real
hover / 按住 / 點選 可試
bgtertiaryneutral-800neutral-100
bgsecondary-pressedneutral-900neutral-300
bgbrand-tint-2brand-900brand-100
textbrand-mainbrand-600
待 dist rebuild
bgbrand-tint-2brand-900brand-100
textbrand-mainbrand-600
fxbrightness-110
bgbrand-tint-2brand-900brand-100
textbrand-mainbrand-600
fxbrightness-90
iconbrand-mainbrand-600
real
bgdisabled-bgneutral-700neutral-100
textgray-3neutral-400neutral-600
real
outline
bgtransparent
textwhiteneutral-0neutral-950
real
hover / 按住 / 點選 可試
bgwhite-2neutral-800neutral-100
bgoutline-pressedneutral-700neutral-100
bgbrand-tint-2brand-900brand-100
textbrand-mainbrand-600
borderbrand-mainbrand-600
待 dist rebuild
bgbrand-tint-2brand-900brand-100
textbrand-mainbrand-600
borderbrand-mainbrand-600
fxbrightness-110
bgbrand-tint-2brand-900brand-100
textbrand-mainbrand-600
borderbrand-mainbrand-600
fxbrightness-90
iconbrand-mainbrand-600
real
bgdisabled-bgneutral-700neutral-100
textgray-3neutral-400neutral-600
bordertransparent
real
outcome-yes
bgoutcome-yes-tintjungle-950jungle-100
textoutcome-yes-solidjungle-500jungle-550
real
hover / 按住 / 點選 可試
bgoutcome-yes-hoverjungle-700jungle-300
textwhiteneutral-0neutral-950
bgoutcome-yes-pressedjungle-550jungle-600
textblackneutral-950neutral-0
bgoutcome-yes-solidjungle-500jungle-550
textblackneutral-950neutral-0
real
bgoutcome-yes-solidjungle-500jungle-550
textblackneutral-950neutral-0
fxbrightness-110
bgoutcome-yes-solidjungle-500jungle-550
textblackneutral-950neutral-0
fxbrightness-90
iconbrand-mainbrand-600
real
bgdisabled-bgneutral-700neutral-100
textgray-3neutral-400neutral-600
real
outcome-no
bgoutcome-no-tintcherry-900cherry-100
textoutcome-no-solidcherry-500cherry-550
real
hover / 按住 / 點選 可試
bgoutcome-no-hovercherry-700cherry-300
textwhiteneutral-0neutral-950
bgoutcome-no-pressedcherry-550cherry-600
textblackneutral-950neutral-0
bgoutcome-no-solidcherry-500cherry-550
textblackneutral-950neutral-0
real
bgoutcome-no-solidcherry-500cherry-550
textblackneutral-950neutral-0
fxbrightness-110
bgoutcome-no-solidcherry-500cherry-550
textblackneutral-950neutral-0
fxbrightness-90
iconbrand-mainbrand-600
real
bgdisabled-bgneutral-700neutral-100
textgray-3neutral-400neutral-600
real
team-home
bgteam-home-bggold-950gold-100
textteam-home-solidgold-500gold-600
real
hover / 按住 / 點選 可試
bgteam-home-hovergold-800gold-300
textwhiteneutral-0neutral-950
bgteam-home-pressedgold-600gold-700
textblackneutral-950neutral-0
bgteam-home-solidgold-500gold-600
textblackneutral-950neutral-0
real
bgteam-home-solidgold-500gold-600
textblackneutral-950neutral-0
fxbrightness-110
bgteam-home-solidgold-500gold-600
textblackneutral-950neutral-0
fxbrightness-90
iconbrand-mainbrand-600
real
bgdisabled-bgneutral-700neutral-100
textgray-3neutral-400neutral-600
real
team-away
bgteam-away-bgsea-900sea-100
textteam-away-solidsea-500sea-565
real
hover / 按住 / 點選 可試
bgteam-away-hoversea-700sea-300
textwhiteneutral-0neutral-950
bgteam-away-pressedsea-565sea-600
textblackneutral-950neutral-0
bgteam-away-solidsea-500sea-565
textblackneutral-950neutral-0
real
bgteam-away-solidsea-500sea-565
textblackneutral-950neutral-0
fxbrightness-110
bgteam-away-solidsea-500sea-565
textblackneutral-950neutral-0
fxbrightness-90
iconbrand-mainbrand-600
real
bgdisabled-bgneutral-700neutral-100
textgray-3neutral-400neutral-600
real
team-draw
bgteam-draw-bgash-900ash-100
textteam-draw-solidash-400ash-600
real
hover / 按住 / 點選 可試
bgteam-draw-hoverash-700
textwhiteneutral-0neutral-950
bgteam-draw-pressedash-500ash-700
textblackneutral-950neutral-0
bgteam-draw-solidash-400ash-600
textblackneutral-950neutral-0
real
bgteam-draw-solidash-400ash-600
textblackneutral-950neutral-0
fxbrightness-110
bgteam-draw-solidash-400ash-600
textblackneutral-950neutral-0
fxbrightness-90
iconbrand-mainbrand-600
real
bgdisabled-bgneutral-700neutral-100
textgray-3neutral-400neutral-600
real

Examples

BLOCK — block=true fills parent width

Spec

ANATOMY

12

1) Button Text

font-face: Manrope
font-weight: 400
font-size: 依 size 而變(見下方 Size & Spacing)
color: 依 skin token 而變(如 text-brand-contrast)

此元件無 iconLeading / iconTrailing prop —— 沒有獨立的「Icon」anatomy 項目;圖示需自行塞進 children。唯一內建的 icon 是 loading 狀態的 Spinner,規格見下方每個 size 的「with icon (loading)」示範。

2) Background

border-radius: rounded-full(實測 9999px,藥丸形)
background-color: 依 skin token 而變(如 bg-brand-main)

寬度無 min-width 限制,由 padding + 內容決定(實測值,非假設)。

SIZE & SPACING

sm
default
with icon (loading)
height 28px
padding-x 12px
font-size 14px (text-bodyM)
line-height 20px
letter-spacing 0.02em
radius rounded-full
spinner size 14px
icon-text gap 8px (mr-2)
md (default)
default
with icon (loading)
height 32px
padding-x 20px
font-size 14px (text-bodyM)
line-height 20px
letter-spacing 0.02em
radius rounded-full
spinner size 16px
icon-text gap 8px (mr-2)
lg
default
with icon (loading)
height 40px
padding-x 28px
font-size 16px (text-bodyL)
line-height 20px
letter-spacing 0.01em
radius rounded-full
spinner size 16px
icon-text gap 8px (mr-2)

數值來源:packages/components/src/components/Button/index.tsx 的 sizeClasses / loadingSize (sm/md/lg),在本頁用 getComputedStyle() 實測,非從 Tailwind class 名稱換算假設。

數值為 2026-06-10 在 dark 模式下的實測(getComputedStyle);source class 對照目前的元件原始碼,色票隨目前的 dark / light 模式即時解析。完整量測、狀態細節與已知不一致見 live-ds-spec/button.md。

Usage

Do

  • 一個區塊只放一顆 brand:它是這裡最主要的動作(下單、Add Funds)。其餘用 secondary 或 outline。
  • 市場選項按鈕依市場類型選 skin:是否會發生 → outcome-yes / outcome-no;陣營 → team-home / team-away / team-draw。
  • 一排互斥選項(時間區間、篩選條件)用 active 標出目前選的那一個。
  • 等待中用 loading,不要自己換文字或加 spinner。

Don't

  • 不要用 brand 色做 YES / NO;市場顏色只走 outcome 與 team 兩組 skin,兩組也不混用。
  • 不要用 className 改顏色、圓角或 hover;需要新外觀就新增 skin。
  • 不要用 className 改高度做第四種尺寸;只有 sm / md / lg。
  • 需要純 icon 按鈕時,留意元件沒有 icon slot、會套用文字按鈕的左右內距(見 Spec 全文)。