WebberUI

Recap Story Scroll

全螢幕逐幕 scroll-snap 敘事卷軸,定格時編排巨型數字與關鍵詞進場,背景色隨主題整幕切換,內建進度點與自動播放。

載入預覽⋯

Playground

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

4500
<RecapStoryScroll />

安裝

npx shadcn@latest add https://webberui.com/r/recap-story-scroll.json

或在 components.json 設定 registries 後,改用 @webberui/recap-story-scroll 安裝。

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

npm install motion lucide-react clsx tailwind-merge

使用

以 compound components 組合:RecapStoryScroll 是 scroll-snap 容器,每個 RecapScene 為一幕,幕內用 RecapStat(巨型數字)與 RecapReveal(接力進場)編排資料。容器高度由 className 決定,各幕會填滿整個容器高度。

import {
  RecapStoryScroll,
  RecapScene,
  RecapStat,
  RecapReveal,
} from "@/components/ui/recap-story-scroll";

<RecapStoryScroll autoPlay className="h-[560px]">
  <RecapScene background="#100a24" label="序章">
    <RecapReveal>
      <p className="text-7xl font-bold">2025</p>
    </RecapReveal>
  </RecapScene>

  <RecapScene background="#1c0b33" label="聆聽">
    <RecapStat value={48210} suffix=" 分鐘" label="總聆聽時長" />
    <RecapReveal delay={0.35}>
      <p className="text-sm text-white/70">相當於 33 天不間斷。</p>
    </RecapReveal>
  </RecapScene>

  <RecapScene background="#0a2418" label="尾聲">
    <RecapReveal>
      <p className="text-4xl font-bold">謝謝你的 2025</p>
    </RecapReveal>
  </RecapScene>
</RecapStoryScroll>

Props

RecapStoryScroll

Prop型別預設值說明
childrenReact.ReactNode放入 RecapScene 子元件,每個為一幕
autoPlaybooleanfalse掛載後是否自動逐幕播放(reduced motion 下強制停用)
autoPlayIntervalnumber4500自動播放時每幕停留時間(毫秒)
loopbooleantrue播完最後一幕是否循環回第一幕
showProgressbooleantrue是否顯示右側幕別進度點
showKeywordsbooleantrue是否顯示底部關鍵詞接力列(取各幕 label
showControlsbooleantrue是否顯示左上幕別計數與播放控制
onSceneChange(index: number) => void定格幕變更時回呼
classNamestring容器樣式;用來設定高度(預設 h-[560px]

RecapScene

Prop型別預設值說明
childrenReact.ReactNode幕內容(RecapStat/RecapReveal 或自訂節點)
backgroundstring#0a0a0a此幕背景色(任一 CSS 顏色值),定格時整幕背景平滑過渡至此色
labelstring幕別標籤,用於進度點提示與底部關鍵詞接力
classNamestring附加在該幕容器上的 class

RecapStat

Prop型別預設值說明
valuenumber目標數值,定格時從 0 計數縮放至此值
prefixstring""數字前綴(例如 "$"
suffixstring""數字後綴(例如 "+""%"
decimalsnumber0小數位數
localestring"en-US"Intl.NumberFormat locale,決定千分位與小數點符號
durationnumber1.4計數動畫時長(秒)
labelstring數字下方的說明文字
classNamestring數字樣式
labelClassNamestring說明文字樣式

RecapReveal

Prop型別預設值說明
childrenReact.ReactNode進場內容(標題、關鍵詞、說明句等)
delaynumber0定格後的進場延遲(秒),用於一幕內多段接力
ynumber20初始垂直位移(px)
classNamestring樣式

細節

  • 逐幕定格:容器為 snap-y snap-mandatory 的捲動區,每幕高度填滿容器;以單一 IntersectionObserver 取最貼近視口者為定格幕。
  • 資料進場:幕內元件透過 context 讀取所在幕是否定格。RecapStat 定格時從 0 計數並縮放進場、離開歸零可重播;RecapRevealdelay 錯開,實作一幕之內關鍵詞逐段接力。
  • 整幕換色:背景色由目前定格幕的 background 驅動,於容器底層平滑過渡(backgroundColor 可插值)。此元件為沉浸式深色畫布,請為各幕帶入偏深的 background 並在需要時以 className 調整文字顏色。
  • 自動播放autoPlay 於掛載後啟動、每 autoPlayInterval 前進一幕;使用者以滾輪或觸控互動時自動暫停,也可用左上按鈕手動切換。
  • 關鍵詞接力:底部依序列出各幕 label,目前定格幕的關鍵詞點亮,其餘淡出,形成交棒式敘事索引。

可及性

  • 使用者系統開啟「減少動態效果」時,保留 scroll-snap 版面與內容(全部直接顯示),停用計數/縮放進場、整幕換色過渡與自動播放,跳幕改為即時捲動。
  • 捲動區可聚焦,支援方向鍵/PageUp/PageDown/Home/End 逐幕導覽;任一鍵盤或滑鼠互動都會暫停自動播放。
  • 右側進度點為原生按鈕,可鍵盤聚焦與點擊跳幕,定格幕以 aria-current 標記;播放鈕帶 aria-pressedaria-label
  • 每幕帶 aria-roledescription="幕"aria-labelRecapStat 計數層對輔助科技隱藏,並以 aria-label 朗讀最終值。

On this page