WebberUI

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.jsonfiles[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型別預設值說明
childrenReact.ReactNode商品卡子元件(放入 ProductCard
editorialsReact.ReactNode[][]依節奏穿插的編輯區塊,會循環取用
cadencenumber3每隔幾張商品卡插入一個編輯區塊
columnsnumber3商品欄數(1–6)
gapnumber16格線間距(px)
staggernumber0.06商品卡進場間隔(秒)
delaynumber0進場前延遲(秒)
oncebooleantrue只在第一次進入視口時播放
classNamestring附加到網格容器的 class

ProductCard

Prop型別預設值說明
titleReact.ReactNode商品名稱
priceReact.ReactNode價格文字
tagReact.ReactNode角標(如「新品」「限量」)
imageReact.ReactNode商品影像節點,未提供時顯示中性佔位
hrefstring連結網址,提供時整卡為 <a>
onSelect() => void點擊回呼,無 href 時整卡為 <button>
childrenReact.ReactNode覆寫影像區內容
classNamestring附加到卡片的 class

EditorialBlock

Prop型別預設值說明
variant"image" | "quote" | "video""image"款式:全幅影像/品牌引言/影片海報
kickerReact.ReactNode眉標(小型標籤)
titleReact.ReactNode主標題(影像/影片款式)
quoteReact.ReactNode引言內容(引言款式)
authorReact.ReactNode引言出處/品牌署名
mediaReact.ReactNode背景媒體節點,未提供時顯示漸層
ctaReact.ReactNode行動呼籲文字
hrefstring行動呼籲連結,提供時整塊可點按
childrenReact.ReactNode覆寫全部內容
classNamestring附加到區塊的 class

動畫細節

  • 編輯區塊:以 clip-path 從中央橫縫向上下擴張進場(inset(46%)inset(0%)),外框展開後內文再輕微上升浮現,營造雜誌拉頁開展的節奏。
  • 商品卡:交錯淡入(opacity + 位移),間隔由 stagger 控制;hover 時影像微幅放大。
  • 影片款式:播放鈕附帶柔和脈動光暈,暗示可播放。
  • 穿插邏輯:走訪商品卡,每滿 cadence 張就插入下一個編輯區塊;末尾不再補插,避免收尾留下孤立區塊。

可及性

  • 使用者系統開啟「減少動態效果」時,直接渲染靜態網格,無 clip-path 擴張、淡入與脈動
  • 商品名稱以 <h3> 呈現,引言款式使用 <blockquote><cite> 語意標籤
  • href 的商品卡渲染為 <a>、僅帶 onSelect 時渲染為 <button>,鍵盤可聚焦並具 focus-visible 外框
  • 編輯區塊的裝飾性圖示(引言、播放、光暈)皆標記 aria-hidden

On this page