互動編排

權限波次解鎖

管理者翻動一個開關,SVG 線路從開關沿路描繪到成員網格,成員頭像依波次逐列解鎖亮起,直觀呈現「一次授權給所有人」。

左側(窄容器時在上方)是管理者卡片與一個開關,右側是成員頭像網格,中間一層 SVG 線路把兩者接起來。開啟時主幹線先從開關右緣描繪出去,再依列序一條條分岔到每一列;支線抵達的那一刻,該列頭像由灰階、半透明加鎖頭的狀態,彈一下變成彩色並換上勾號徽章——一波接一波,直到所有人都拿到權限。關閉時反向:從最後一列開始往回收線,頭像依序回到鎖定。開關狀態支援受控/非受控雙模式。

把這個效果裝進你的專案

在專案資料夾執行指令,CLI 會加入原始碼與依賴套件,再依下方使用範例引用元件。

npx webberui@latest add permission-wave-grid

還沒有專案,或安裝遇到問題?看快速開始 →

Playground

即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。

6
160
400
編輯中的呼叫預設屬性
<PermissionWaveGrid/>

完整範例包含預覽的排版與資料。先安裝元件,再把範例檔貼入你的專案。

安裝

npx webberui@latest add https://webberui.com/r/permission-wave-grid.json

或在 components.json 設定 registries 後,改用 @webberui/permission-wave-grid 安裝。

使用

import { PermissionWaveGrid } from "@/components/ui/permission-wave-grid";

const members = [
  { id: "1", name: "王小明" },
  { id: "2", name: "林怡君" },
  { id: "3", name: "陳家豪", initials: "家豪", color: "#0f766e" },
];

<PermissionWaveGrid
  members={members}
  columns={6}
  switchLabel="允許所有成員檢視財務報表"
  onEnabledChange={(enabled) => console.log(enabled ? "已開放" : "已收回")}
/>

Props

Prop型別預設值說明
membersPermissionWaveMember[]—成員清單,依序排入網格
columnsnumber6網格欄數
enabledboolean—受控的開關狀態;未提供時由元件內部管理(非受控)
defaultEnabledbooleanfalse非受控模式的初始開關狀態
onEnabledChange(enabled: boolean) => void—開關切換時回呼
adminLabelstring"管理者"管理者卡片標題
switchLabelstring"允許所有成員存取"開關旁的說明文字,同時是開關的無障礙名稱
trunkDurationnumber400主幹線路描繪時長(毫秒)
waveDelaynumber160每一列支線之間的間隔(毫秒),即波次節奏
pulsebooleantrue授權完成後是否在線路上跑光點
accentstring"#3b82f6"強調色,寫入 --wb-permission-wave-accent
classNamestring—併入最外層容器

PermissionWaveMember

欄位型別預設值說明
idstring—唯一識別碼,也用來確定性分配預設色彩
namestring—成員名稱,用於頭像的 aria-label 與滑鼠提示
initialsstring—頭像縮寫;未提供時由名稱推導(中文取末兩字、拉丁字母取字首)
colorstring—頭像底色;未提供時依 id 從中性色為主的色盤確定性分配

另外具名匯出 getMemberInitials(name),方便在其他地方用同一套縮寫規則。

細節

  • 線路座標用實際量測的 DOM 位置計算:主幹從開關右緣出發往右,到網格左側的匯流點後分岔成每列一條直角折線支線,轉角帶 8px 圓角;容器變窄時版面改成上下排列,主幹改從開關下緣往下再轉入網格左側。ResizeObserver 會在版面變動時重算。
  • 開啟的時間線:主幹描繪 trunkDuration → 第 r 列支線在 trunkDuration + r × waveDelay 開始描繪(300ms)→ 支線抵達後該列頭像以 0.9 → 1.06 → 1 的彈跳解鎖,列內每個頭像再錯開 30ms。關閉時由最後一列往回收線,最後才收主幹。
  • 波次跑完後,若 pulse 開啟,每條路徑上會有一顆光點以 CSS offset-path 沿線移動;時長讀取 --wb-permission-wave-pulse(預設 1600ms)。開關滑塊的位移時長是 --wb-permission-wave-thumb(預設 150ms)。
  • 快速連點時動畫會從當下狀態直接轉向,光點只在最新一次開啟完整跑完後才出現。

可及性

  • 開關是 role="switch" 的原生按鈕,帶 aria-checked,以 aria-labelledby 指向 switchLabel;空白鍵與 Enter 皆可切換,並有 focus-visible 外框
  • 成員網格是 role="list",每個頭像的 aria-label 為「王小明:已授權」或「王小明:未授權」
  • 波次完成後由 aria-live="polite" 區域宣告「已授權 24 位成員」(關閉時宣告已收回)
  • SVG 線路層與光點皆設 aria-hidden,不干擾輔助科技
  • 使用者系統開啟「減少動態效果」時,線路直接出現或消失、所有頭像同時以短淡入切換,不跑光點