互動編排
權限波次解鎖
管理者翻動一個開關,SVG 線路從開關沿路描繪到成員網格,成員頭像依波次逐列解鎖亮起,直觀呈現「一次授權給所有人」。
左側(窄容器時在上方)是管理者卡片與一個開關,右側是成員頭像網格,中間一層 SVG 線路把兩者接起來。開啟時主幹線先從開關右緣描繪出去,再依列序一條條分岔到每一列;支線抵達的那一刻,該列頭像由灰階、半透明加鎖頭的狀態,彈一下變成彩色並換上勾號徽章——一波接一波,直到所有人都拿到權限。關閉時反向:從最後一列開始往回收線,頭像依序回到鎖定。開關狀態支援受控/非受控雙模式。
把這個效果裝進你的專案
在專案資料夾執行指令,CLI 會加入原始碼與依賴套件,再依下方使用範例引用元件。
npx webberui@latest add permission-wave-gridPlayground
即時調整 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 | 型別 | 預設值 | 說明 |
|---|---|---|---|
members | PermissionWaveMember[] | — | 成員清單,依序排入網格 |
columns | number | 6 | 網格欄數 |
enabled | boolean | — | 受控的開關狀態;未提供時由元件內部管理(非受控) |
defaultEnabled | boolean | false | 非受控模式的初始開關狀態 |
onEnabledChange | (enabled: boolean) => void | — | 開關切換時回呼 |
adminLabel | string | "管理者" | 管理者卡片標題 |
switchLabel | string | "允許所有成員存取" | 開關旁的說明文字,同時是開關的無障礙名稱 |
trunkDuration | number | 400 | 主幹線路描繪時長(毫秒) |
waveDelay | number | 160 | 每一列支線之間的間隔(毫秒),即波次節奏 |
pulse | boolean | true | 授權完成後是否在線路上跑光點 |
accent | string | "#3b82f6" | 強調色,寫入 --wb-permission-wave-accent |
className | string | — | 併入最外層容器 |
PermissionWaveMember
| 欄位 | 型別 | 預設值 | 說明 |
|---|---|---|---|
id | string | — | 唯一識別碼,也用來確定性分配預設色彩 |
name | string | — | 成員名稱,用於頭像的 aria-label 與滑鼠提示 |
initials | string | — | 頭像縮寫;未提供時由名稱推導(中文取末兩字、拉丁字母取字首) |
color | string | — | 頭像底色;未提供時依 id 從中性色為主的色盤確定性分配 |
另外具名匯出 getMemberInitials(name),方便在其他地方用同一套縮寫規則。
細節
- 線路座標用實際量測的 DOM 位置計算:主幹從開關右緣出發往右,到網格左側的匯流點後分岔成每列一條直角折線支線,轉角帶 8px 圓角;容器變窄時版面改成上下排列,主幹改從開關下緣往下再轉入網格左側。
ResizeObserver會在版面變動時重算。 - 開啟的時間線:主幹描繪
trunkDuration→ 第 r 列支線在trunkDuration + r × waveDelay開始描繪(300ms)→ 支線抵達後該列頭像以 0.9 → 1.06 → 1 的彈跳解鎖,列內每個頭像再錯開 30ms。關閉時由最後一列往回收線,最後才收主幹。 - 波次跑完後,若
pulse開啟,每條路徑上會有一顆光點以 CSSoffset-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,不干擾輔助科技 - 使用者系統開啟「減少動態效果」時,線路直接出現或消失、所有頭像同時以短淡入切換,不跑光點