Design SystemGuidelinesInteraction States

Interaction States

pressed ≠ selected

互動狀態分兩層,不可合併:

層State性質怎麼觸發
Interaction
短暫、使用者操作中
hover指標移入hover:
pressed手指 / 滑鼠正在按下pressed:(React Aria data-pressed)
focus鍵盤焦點focus-visible:(目前全站無 focus ring,重新引入需對照線上並拍板)
disabled / loading由 prop 關閉 / 等待中disabled: / data-loading:
Selection
持久、由邏輯控制
selected目前被選中的那一個tabs、radio、checkbox、menu item、outcome 按鈕
on / off開關toggle、switch

「active」禁止當 state 名稱。這個詞在 CSS 是 :active、在 React Aria 是 pressed、在口語是「目前選中」, 三種意思撞在一起。遇到就改成 pressed 或 selected。@olab/components Button 的 active prop 是 production 既有命名,語意是 selected,不在此規則內。

示意:selected 是持久的,pressed 只在按下的瞬間

按住不放 = pressed;放開後留下的 = selected

Pressed 一定要看得到

  • 每一個互動元件在按下的瞬間都要有即時回饋,light / dark 都要看得出來。
  • pressed 走 interaction layer(pressed: variant),禁止存進 state、禁止用 isPressed 這類 prop 對外控制、禁止當持久狀態用。
  • Live DS 的 family 色只有「淡底 + 一個 solid」兩階,沒有更深的 pressed 階,所以 pressed 與 selected+hover 用 brightness 做回饋( brightness-90 / brightness-110)。
  • 新增或修改互動元件時,preview 頁的 Interactive Demo 必須能按出 pressed,否則不算完成。

手機沒有 hover

觸控螢幕上 hover 不存在。桌機靠 hover 才看得出「這個可以點」的設計,到手機上會變成死的。

  • 靜止狀態就要看得出可點:品牌色、常駐底線、按鈕外觀,不能把可點性藏在 hover 裡。
  • 以 pressed 回饋取代 hover 回饋——這也是上一節 pressed 必須可見的原因之一。
  • web 上寫的 DS hover 規則套到手機之前,先檢查沒有 hover 時這個元件還成不成立。

禁止事項

  • 自訂 hover 顏色、pressed / selected 樣式,或用 className 覆寫 component 的 interaction。
  • 用 div / span + onClick 模擬按鈕——一律用 Button / ButtonUtility。
  • 在 React Aria 元件上用 CSS active:(它不觸發 :active)——用 pressed:。
  • 手動控制 focus ring。
  • disabled 用 family 色降不透明度——走 disabled:opacity-50 的中性做法。