Theme / v2.15.0

UI UX Pro Max

把模糊需求變成可實作、可驗收的介面

基礎觀念

微互動與動畫過渡

理解微互動的觸發、回饋和狀態,使用 CSS 建立有目的的過渡動畫,並支援 prefers-reduced-motion。

微互動與動畫過渡

微互動不是「讓頁面動起來」;它是使用者操作後收到的回應。按鈕是否已經被按下?資料是否正在儲存?錯誤要如何恢復?如果動畫沒有回答這些問題,就只是噪音。

一個互動的四個部分

以「儲存設定」為例:

部分 設計問題 具體結果
Trigger 什麼會開始互動? 使用者按下儲存
Feedback 使用者需要知道什麼? 按鈕進入儲存中
State 中途與完成後怎麼看? loading、success、error
Recovery 失敗後能做什麼? 保留輸入並提供重試

這份表可以直接成為 AI 實作元件時的提示上下文。

用 CSS 實作按鈕回饋

<button class="button" type="submit">
  <span class="button__label">儲存設定</span>
  <span class="button__spinner" aria-hidden="true"></span>
</button>
.button {
  transition:
    background-color 160ms ease,
    box-shadow 160ms ease,
    transform 160ms ease;
}

.button:hover {
  box-shadow: 0 4px 12px rgb(37 99 235 / 0.24);
}

.button:active {
  transform: translateY(1px);
}

.button[data-loading='true'] .button__label {
  opacity: 0.7;
}

不要使用 transition: all。它會讓尺寸、位置和其他未預期改變的屬性也加入動畫,造成 layout shift 和難以測試的行為。

loading 不是 success

async function saveSettings(form, button) {
  button.dataset.loading = 'true';
  button.disabled = true;

  try {
    await save(form);
    button.dataset.loading = 'false';
    button.dataset.status = 'success';
  } catch (error) {
    button.dataset.loading = 'false';
    button.disabled = false;
    showError('儲存失敗,請檢查網路後重試。');
  }
}

動畫只能補充狀態,不能代替文字、ARIA 或可操作的錯誤訊息。

尊重減少動態偏好

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

課後練習

為一個搜尋框設計 idle、typing、loading、empty 和 error 五種狀態。先用文字列出狀態,再決定哪些地方需要動畫,最後用鍵盤和 prefers-reduced-motion 測試。

下一課會把這些互動規則與語意 HTML、鍵盤操作和錯誤訊息結合。