WebberUI

Data Duel Split

頁面級 A/B 對決分屏,逐回合捲動揭示指標,中央分界線像拔河般滑移、底部累計比分同步跳動。

載入預覽⋯

Playground

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

300
<DataDuelSplit />

安裝

npx shadcn@latest add https://webberui.com/r/data-duel-split.json

或在 components.json 設定 registries 後,改用 @webberui/data-duel-split 安裝。

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

npm install motion clsx tailwind-merge

使用

import { DataDuelSplit } from "@/components/ui/data-duel-split";

<DataDuelSplit
  left={{ name: "Nova" }}
  right={{ name: "Atlas" }}
  rounds={[
    { label: "首屏載入", left: 420, right: 680, suffix: "ms", win: "lower" },
    { label: "轉換率", left: 3.1, right: 4.6, suffix: "%", format: (v) => v.toFixed(1) },
    { label: "月活躍用戶", left: 128, right: 96, suffix: "k" },
  ]}
/>

預設以整個視窗為捲動容器、舞台高度為 100vh,直接放進頁面即可成為一段捲動敘事。若要嵌在某個 overflow-y-auto 區塊裡,將該區塊的 ref 傳給 container,並把 stageHeight 設成固定像素:

const scrollerRef = React.useRef<HTMLDivElement>(null);

<div ref={scrollerRef} className="h-[300px] overflow-y-auto">
  <DataDuelSplit container={scrollerRef} stageHeight="300px" left={/* … */} right={/* … */} rounds={/* … */} />
</div>

Props

DataDuelSplit

Prop型別預設值說明
leftDuelTeam左方陣營設定
rightDuelTeam右方陣營設定
roundsDuelRound[]逐回合對決資料,依捲動順序揭示
stageHeightstring"100vh"舞台高度(CSS 長度);巢狀容器內建議傳固定像素
containerRefObject<HTMLElement | null>巢狀 overflow 捲動容器的 ref;預設以視窗為捲動容器
classNamestring附加在最外層容器的 class

DuelTeam

欄位型別預設值說明
namestring陣營名稱
accentstring#4f46e5/右 #e11d48強調色(任意 CSS 顏色),用於填充、比分與勝方數值
iconReact.ReactNode顯示在名稱旁的小圖示或標誌

DuelRound

欄位型別預設值說明
labelstring該回合對比的指標名稱
leftnumber左方數值
rightnumber右方數值
format(value: number) => stringtoLocaleString數值格式化函式
suffixstring數值後綴,例如 "%""ms""k"
noteReact.ReactNode該回合的補充說明
win"higher" | "lower""higher"勝負判定:數值高者勝或低者勝

細節

  • 拔河分界線:以 useScroll 取得捲動進度,在各回合的優勢佔比之間連續插值,再套一層 useSpring 讓分界線帶點慣性,像被兩側拉扯的繩子。優勢佔比夾在 12%–88% 之間,確保兩側標籤永遠可見。
  • 累計比分:比分只計入「目前回合(含)之前」的勝負,回合切換時分數以 spring 彈跳呈現「跳動」感。win: "lower" 的回合以數值較低者為勝方。
  • 回合值揭示:每回合的指標數字在進場時由 0 spring 到目標值;整數維持整數、含小數則保留小數。
  • 巢狀捲動:容器最外層高度為 stageHeight × 回合數,內部舞台以 sticky top-0 釘住。透過 container 支援在任意 overflow-y-auto 區塊內捲動。

可及性

  • 使用者系統開啟「減少動態效果」時,改以靜態的逐列對比長條與最終比分呈現,不再依賴捲動與動畫。
  • 視覺舞台對輔助科技隱藏(aria-hidden),另提供一份 sr-only 的完整摘要清單,逐回合朗讀雙方數值與勝方。
  • 最外層以 role="group" 搭配 aria-label 標記整段對決,方便輔助科技辨識區塊用途。

On this page