WebberUI

Rank Shuffle Board

資料驅動的排名洗牌榜:分數更新時列以 FLIP 動畫互換位置、名次升降閃動箭頭,前三名帶金銀銅頒獎台語彙。

載入預覽⋯

安裝

npx shadcn@latest add https://webberui.com/r/rank-shuffle-board.json

或在 components.json 設定 registries 後,改用 @webberui/rank-shuffle-board 安裝。

安裝依賴後,從 registry JSON(/r/rank-shuffle-board.jsonfiles[0].content)複製 rank-shuffle-board.tsx 原始碼到你的 components/ui/ 目錄:

npm install motion clsx tailwind-merge

使用

import { RankShuffleBoard } from "@/components/ui/rank-shuffle-board";

const entries = [
  { id: "amy", name: "Amy", score: 2480 },
  { id: "ben", name: "Ben", score: 2210 },
  { id: "cleo", name: "Cleo", score: 1975 },
];

<RankShuffleBoard entries={entries} unit="pt" />

排序在元件內部完成——只要更新 entries 的分數,列就會自動以 FLIP 動畫換位。id 必須穩定(不要用陣列索引),FLIP 才能正確配對前後位置。

搭配頭像:

<RankShuffleBoard
  unit="分"
  entries={members.map((m) => ({
    id: m.id,
    name: m.name,
    score: m.score,
    avatar: <img src={m.avatarUrl} alt="" className="size-8 rounded-full" />,
  }))}
/>

Props

RankShuffleBoard

Prop型別預設值說明
entriesRankShuffleEntry[]排行榜項目,元件內部依 score 由高到低穩定排序(同分保持原序)
unitstring分數後的單位文字(例如 pt
classNamestring附加到最外層 <ol> 的 class

RankShuffleEntry

欄位型別說明
idstring穩定唯一識別碼,FLIP 動畫據此配對列的前後位置
namestring顯示名稱
scorenumber分數,元件內部依此由高到低排序
avatarReact.ReactNode名稱左側的頭像(可選)

細節

  • FLIP 換位:列以 Motion layout 動畫(spring)連續滑到新名次,key 用穩定 id 配對前後位置,而非淡出重繪
  • 升降箭頭:元件以 ref 記錄前一次名次,名次改變的列會短暫閃動箭頭(升 ↑ 綠 / 降 ↓ 紅),1.5 秒後由 AnimatePresence 淡出;1.5 秒內再次變動會重置方向與倒數。箭頭放在固定寬度插槽中,出現/消失不會推擠分數
  • 頒獎台語彙:前三名帶金(amber)/銀(slate)/銅(orange)左緣色帶,名次徽章放大並套用對應配色;第四名起為中性配色
  • 分數 spring 補間:分數以 MotionValue 直接寫入 DOM(不觸發 React re-render),spring 過渡到新值,千分位逗號、捨入到整數顯示
  • 穩定排序:以原始索引作 tiebreak,同分項目保持傳入順序,不會無故互換

可及性

  • 使用者系統開啟「減少動態效果」時,FLIP 停用(列直接跳到新位置)、分數直接顯示最終值,箭頭不播淡入淡出(DOM 結構與 SSR 一致)
  • 分數容器帶 aria-label(最終格式化值,含單位),補間中的動畫 span 對輔助科技隱藏(aria-hidden),螢幕閱讀器只會朗讀最終值
  • 榜單為語意化的 <ol> 有序清單;升降箭頭與色帶為裝飾性元素,皆標記 aria-hidden

On this page