WebberUI

Versus Tray

勾選商品後自底部滑出比較盤,縮圖 FLIP 飛入全幅規格表並逐列掃描標記每列優勝者。

載入預覽⋯

Playground

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

4
4
260
<VersusTray />

安裝

npx shadcn@latest add https://webberui.com/r/versus-tray.json

或在 components.json 設定 registries 後,改用 @webberui/versus-tray 安裝。

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

npm install motion lucide-react clsx tailwind-merge

使用

import {
  VersusTray,
  type VersusProduct,
  type VersusSpec,
} from "@/components/ui/versus-tray";

const specs: VersusSpec[] = [
  { key: "price", label: "價格", better: "lower", unit: " 元" },
  { key: "battery", label: "續航", better: "higher", unit: " 小時" },
  { key: "os", label: "系統" },
];

const products: VersusProduct[] = [
  {
    id: "a",
    name: "Aero X1",
    subtitle: "旗艦輕薄",
    specs: { price: 27900, battery: 22, os: "Android 15" },
  },
  {
    id: "b",
    name: "Nova Pro",
    subtitle: "影像旗艦",
    specs: { price: 31900, battery: 20, os: "Android 15" },
  },
];

<VersusTray products={products} specs={specs} maxSelect={4} />;

Props

VersusTray

Prop型別預設值說明
productsVersusProduct[]商品清單
specsVersusSpec[]規格列定義,依序作為表格每一列
selectedIdsstring[]受控:已勾選商品 id
defaultSelectedIdsstring[][]非受控模式的初始勾選
onSelectedChange(ids: string[]) => void勾選變更時觸發
onCompareChange(comparing: boolean) => void進入/離開比較檢視時觸發
maxSelectnumber4最多可同時比較的數量
columnsnumber3商品網格欄數
scanIntervalnumber260逐列掃描每列的間隔(毫秒)
compareLabelstring"比較"比較鈕文字
backLabelstring"返回挑選"返回挑選鈕文字
hideSameLabelstring"只看差異"「只看差異」切換文字

VersusSpec

欄位型別說明
keystring規格識別 key,對應 product.specs 的索引
labelstring列首顯示名稱
better"higher" | "lower" | "none"優勝方向,none(預設)不比較
unitstring顯示單位,接在數值之後
format(value) => ReactNode自訂值呈現,覆寫預設格式

VersusProduct

欄位型別說明
idstring唯一識別 key
namestring商品名稱
subtitlestring副標(價格、型號等)
thumbnailReactNode縮圖內容,未提供時以名稱首字佔位
specsRecord<string, string | number | boolean | null>規格值表

細節

  • 收集盤:勾選商品後,比較盤以 spring 自容器底部滑出;chip 進出場與重排皆帶動畫,可逐一移除。
  • FLIP 飛入:點「比較」時,收集盤中的縮圖以共享 layoutId 飛入並放大為規格表的欄首,返回時再飛回原位。
  • 逐列掃描:進入比較後依 scanInterval 逐列點亮,掃描當下整列閃過高光。
  • 優勝標記:依 better 方向找出每列最佳值(數值型,支援並列),以綠色底色脈衝與勾號標示;掃描結束後為勝出列數最多且唯一的商品欄首加上領先徽章。
  • 只看差異:一鍵隱藏所有商品值相同的列,其餘列以 FLIP 補位。
  • 布林值預設呈現為「有/無」,可用 format 自訂任意型別的顯示。

可及性

  • 商品卡片為 role="checkbox" 並帶 aria-checked,可用鍵盤聚焦與 Enter/Space 勾選;達 maxSelect 上限時未選卡片 disabled
  • 規格表使用 role="table" / row / columnheader / rowheader / cell 語意,優勝格帶「最佳」標籤、領先徽章帶「領先」隱藏文字。
  • 收集盤為 role="region",移除鈕帶對應 aria-label;「只看差異」切換帶 aria-pressed
  • 使用者系統開啟「減少動態效果」時,滑出、FLIP 飛行與掃描皆停用,規格表直接呈現完整結果與優勝標記。

On this page