媒體

封面牆

由中心向外逐格填入的封面格子牆 React 元件,中央疊放逐位滾動的計數與文案,滑過單格推近、鄰格微退,可點擊選取。

把一整面書封、專輯或作品縮圖排成網格,進入視口時逐格浮現——每格由模糊、略小、透明淡入到定位。填入順序可選由中心向外、逐列或確定性打亂;網格中央疊放一層放射狀遮罩,上面是逐位滾動的計數數字、標題與說明。滑鼠滑過單格時該格推近、陰影加深,周圍八格微微退後;傳入 onSelect 後每格都是可點擊的按鈕。

把這個效果裝進你的專案

在專案資料夾執行指令,CLI 會加入原始碼與依賴套件,再依下方使用範例引用元件。

npx webberui@latest add cover-wall

還沒有專案,或安裝遇到問題?看快速開始 →

Playground

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

28
500
6
編輯中的呼叫預設屬性
<CoverWall/>

完整範例包含預覽的排版與資料。先安裝元件,再把範例檔貼入你的專案。

安裝

npx webberui@latest add https://webberui.com/r/cover-wall.json

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

使用

import { CoverWall } from "@/components/ui/cover-wall";

<CoverWall
  images={covers} // { src: string; alt: string }[]
  columns={6}
  order="center-out"
  counter={500}
  counterSuffix="+"
  title="本月新書牆"
  description="本好書陸續上架"
  onSelect={(index) => console.log(covers[index].alt)}
/>

沒有圖片時也可以直接放任意格子內容:

<CoverWall columns={5} aspect="1/1">
  {albums.map((album) => (
    <AlbumTile key={album.id} album={album} />
  ))}
</CoverWall>

Props

Prop型別預設值說明
imagesCoverWallImage[]—封面圖片陣列;未提供時改用 children,每個子元素是一格
childrenReact.ReactNode—任意格子內容(每個子元素一格);有 images 時忽略
columnsnumber6欄數;螢幕寬度小於 640px 時最多 4 欄
aspectstring"3/4"每格的長寬比(CSS aspect-ratio),圖片載入前先預留空間
gapnumber6格子間距(px)
order"center-out" | "row" | "random""center-out"填入順序:由中心向外、逐列、確定性打亂
staggernumber28每格之間的延遲(ms);未提供時讀 --wb-cw-stagger
counternumber | nullnull中央疊放的計數數字;null 時不顯示
counterSuffixstring"+"計數數字後綴
titleReact.ReactNode—中央標題
descriptionReact.ReactNode—中央說明文字
onSelect(index: number) => void—點擊格子(或聚焦後按 Enter/空白鍵)時回呼,參數為格子索引;提供時每格變成按鈕
classNamestring—透傳到最外層容器

CoverWallImage

欄位型別預設值說明
srcstring—圖片網址(使用者自己的圖;元件不內建任何外部圖片)
altstring—替代文字;可點擊時同時作為按鈕的 aria-label

細節

  • 填入:網格進入視口(IntersectionObserver,只觸發一次)後,每格依排名延遲 排名 × stagger,以 420ms 從 opacity 0、scale(0.9)、blur(6px) 過渡到定位。
  • 順序:center-out 依格子到網格中心的歐氏距離排序;row 由左上逐列;random 以 index 的確定性雜湊打亂,SSR 與瀏覽器結果一致。窄螢幕切成 4 欄時順序與鄰格會依實際欄數重算。
  • 計數:每一位是 0–9 的直列滾輪,以 spring(stiffness 120、damping 20)滾到目標位,在填入進度約 60% 時開始。
  • 圖片以 loading="lazy"、decoding="async"、object-cover 載入,外層 aspect-ratio 先預留空間,不會跳版。
  • 可覆寫的 CSS 變數:--wb-cw-stagger(28ms)、--wb-cw-fill-duration(420ms)、--wb-cw-hover-duration(200ms)、--wb-cw-ease(cubic-bezier(0.23,1,0.32,1))、--wb-cw-scrim(中央遮罩色,預設 neutral-950 的 70%)。
  • hover 推近只在精準指標(滑鼠、觸控板)生效,觸控裝置點擊不會縮放。

可及性

  • 格子是 ul/li 清單;傳入 onSelect 時每格是 type="button",可用 Tab 聚焦、Enter/空白鍵選取,並有 focus-visible 外框
  • 使用 images 且可點擊時,按鈕以圖片 alt 作為 aria-label;不可點擊時圖片保留原本的 alt
  • 中央疊層不攔截指標;計數區 aria-live="off",螢幕閱讀器只讀完整數值,滾動中的位數以 aria-hidden 隱藏
  • 使用者系統開啟「減少動態效果」時,所有格子直接出現、計數直接顯示最終值,hover 只加深陰影、不縮放也不讓鄰格退後