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
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。
| skin | default | hover | pressed | selected | selected+hover | selected+pressed | loading | disabled |
|---|---|---|---|---|---|---|---|---|
| brand | bgbrand-mainbrand-600 textbrand-contrastneutral-950neutral-0 real | 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 | bgtertiaryneutral-800neutral-100 | bgsecondary-pressedneutral-900neutral-300 | bgbrand-tint-2brand-900brand-100 textbrand-mainbrand-600 | 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 | bgwhite-2neutral-800neutral-100 | bgoutline-pressedneutral-700neutral-100 | bgbrand-tint-2brand-900brand-100 textbrand-mainbrand-600 borderbrand-mainbrand-600 | 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 | 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 | 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 | 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 | 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 | 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
1) Button Text
font-face: Manropefont-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
數值來源: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 全文)。
Links
- Measured spec
- live-ds-spec/button.md