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.json 的 files[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 | 型別 | 預設值 | 說明 |
|---|---|---|---|
products | VersusProduct[] | — | 商品清單 |
specs | VersusSpec[] | — | 規格列定義,依序作為表格每一列 |
selectedIds | string[] | — | 受控:已勾選商品 id |
defaultSelectedIds | string[] | [] | 非受控模式的初始勾選 |
onSelectedChange | (ids: string[]) => void | — | 勾選變更時觸發 |
onCompareChange | (comparing: boolean) => void | — | 進入/離開比較檢視時觸發 |
maxSelect | number | 4 | 最多可同時比較的數量 |
columns | number | 3 | 商品網格欄數 |
scanInterval | number | 260 | 逐列掃描每列的間隔(毫秒) |
compareLabel | string | "比較" | 比較鈕文字 |
backLabel | string | "返回挑選" | 返回挑選鈕文字 |
hideSameLabel | string | "只看差異" | 「只看差異」切換文字 |
VersusSpec
| 欄位 | 型別 | 說明 |
|---|---|---|
key | string | 規格識別 key,對應 product.specs 的索引 |
label | string | 列首顯示名稱 |
better | "higher" | "lower" | "none" | 優勝方向,none(預設)不比較 |
unit | string | 顯示單位,接在數值之後 |
format | (value) => ReactNode | 自訂值呈現,覆寫預設格式 |
VersusProduct
| 欄位 | 型別 | 說明 |
|---|---|---|
id | string | 唯一識別 key |
name | string | 商品名稱 |
subtitle | string | 副標(價格、型號等) |
thumbnail | ReactNode | 縮圖內容,未提供時以名稱首字佔位 |
specs | Record<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 飛行與掃描皆停用,規格表直接呈現完整結果與優勝標記。