Editorial Interleave Grid
編輯式穿插網格:商品網格每隔 N 張卡片自動插入全幅影像、引言或影片區塊,形成雜誌式韻律。
載入預覽⋯
Playground
即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。
3
3
16
0.06
<EditorialInterleaveGrid />
安裝
npx shadcn@latest add https://webberui.com/r/editorial-interleave-grid.json或在 components.json 設定 registries 後,改用 @webberui/editorial-interleave-grid 安裝。
安裝依賴後,從 registry JSON(/r/editorial-interleave-grid.json 的 files[0].content)複製 editorial-interleave-grid.tsx 原始碼到你的 components/ui/ 目錄:
npm install motion lucide-react clsx tailwind-merge使用
商品卡以 children 傳入,編輯區塊以 editorials 陣列傳入。網格會每隔 cadence 張商品卡插入一個編輯區塊,並循環取用 editorials。
import {
EditorialInterleaveGrid,
ProductCard,
EditorialBlock,
} from "@/components/ui/editorial-interleave-grid";
<EditorialInterleaveGrid
columns={3}
cadence={3}
editorials={[
<EditorialBlock
key="hero"
variant="image"
kicker="Autumn 2026"
title="回歸自然色調"
cta="探索系列"
href="/collections/autumn"
media={<img src="/hero.jpg" alt="" />}
/>,
<EditorialBlock
key="quote"
variant="quote"
quote="好的設計,是把喧囂留在門外。"
author="— 品牌主理人"
/>,
<EditorialBlock
key="film"
variant="video"
kicker="Behind the seams"
title="工坊的一天"
media={<img src="/poster.jpg" alt="" />}
/>,
]}
>
{items.map((item) => (
<ProductCard
key={item.id}
title={item.name}
price={item.price}
tag={item.tag}
href={item.url}
image={<img src={item.image} alt="" />}
/>
))}
</EditorialInterleaveGrid>Props
EditorialInterleaveGrid
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
children | React.ReactNode | — | 商品卡子元件(放入 ProductCard) |
editorials | React.ReactNode[] | [] | 依節奏穿插的編輯區塊,會循環取用 |
cadence | number | 3 | 每隔幾張商品卡插入一個編輯區塊 |
columns | number | 3 | 商品欄數(1–6) |
gap | number | 16 | 格線間距(px) |
stagger | number | 0.06 | 商品卡進場間隔(秒) |
delay | number | 0 | 進場前延遲(秒) |
once | boolean | true | 只在第一次進入視口時播放 |
className | string | — | 附加到網格容器的 class |
ProductCard
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
title | React.ReactNode | — | 商品名稱 |
price | React.ReactNode | — | 價格文字 |
tag | React.ReactNode | — | 角標(如「新品」「限量」) |
image | React.ReactNode | — | 商品影像節點,未提供時顯示中性佔位 |
href | string | — | 連結網址,提供時整卡為 <a> |
onSelect | () => void | — | 點擊回呼,無 href 時整卡為 <button> |
children | React.ReactNode | — | 覆寫影像區內容 |
className | string | — | 附加到卡片的 class |
EditorialBlock
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
variant | "image" | "quote" | "video" | "image" | 款式:全幅影像/品牌引言/影片海報 |
kicker | React.ReactNode | — | 眉標(小型標籤) |
title | React.ReactNode | — | 主標題(影像/影片款式) |
quote | React.ReactNode | — | 引言內容(引言款式) |
author | React.ReactNode | — | 引言出處/品牌署名 |
media | React.ReactNode | — | 背景媒體節點,未提供時顯示漸層 |
cta | React.ReactNode | — | 行動呼籲文字 |
href | string | — | 行動呼籲連結,提供時整塊可點按 |
children | React.ReactNode | — | 覆寫全部內容 |
className | string | — | 附加到區塊的 class |
動畫細節
- 編輯區塊:以
clip-path從中央橫縫向上下擴張進場(inset(46%)→inset(0%)),外框展開後內文再輕微上升浮現,營造雜誌拉頁開展的節奏。 - 商品卡:交錯淡入(
opacity+ 位移),間隔由stagger控制;hover 時影像微幅放大。 - 影片款式:播放鈕附帶柔和脈動光暈,暗示可播放。
- 穿插邏輯:走訪商品卡,每滿
cadence張就插入下一個編輯區塊;末尾不再補插,避免收尾留下孤立區塊。
可及性
- 使用者系統開啟「減少動態效果」時,直接渲染靜態網格,無 clip-path 擴張、淡入與脈動
- 商品名稱以
<h3>呈現,引言款式使用<blockquote>與<cite>語意標籤 - 帶
href的商品卡渲染為<a>、僅帶onSelect時渲染為<button>,鍵盤可聚焦並具focus-visible外框 - 編輯區塊的裝飾性圖示(引言、播放、光暈)皆標記
aria-hidden