WebberUI

Sticky Reveal

吸頂圖文對照揭示:左側文字隨捲動流動,右側視覺吸附固定並交叉切換。

載入預覽⋯

Playground

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

24
<StickyReveal />

安裝

npx shadcn@latest add https://webberui.com/r/sticky-reveal.json

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

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

npm install motion clsx tailwind-merge

使用

StickyRevealItem 宣告每一段對照,media 放右側吸頂視覺、children 放左側文字:

import { StickyReveal, StickyRevealItem } from "@/components/ui/sticky-reveal";

<StickyReveal>
  <StickyRevealItem media={<img src="/design.jpg" alt="設計" className="h-full w-full object-cover" />}>
    <h3 className="text-2xl font-semibold">設計</h3>
    <p className="mt-2 text-neutral-600">從語意化 token 出發,全站節奏一致。</p>
  </StickyRevealItem>

  <StickyRevealItem media={<img src="/ship.jpg" alt="發佈" className="h-full w-full object-cover" />}>
    <h3 className="text-2xl font-semibold">發佈</h3>
    <p className="mt-2 text-neutral-600">一鍵安裝,內建 reduced-motion。</p>
  </StickyRevealItem>
</StickyReveal>

若內容位於巢狀捲動容器中,將該容器 ref 透過 container 傳入(頁面級捲動則可省略):

const scrollerRef = React.useRef<HTMLDivElement>(null);

<div ref={scrollerRef} className="h-[80vh] overflow-y-auto">
  <StickyReveal container={scrollerRef} stickyTop={16}>
    {/* ...StickyRevealItem */}
  </StickyReveal>
</div>

Props

StickyReveal

Prop型別預設值說明
childrenReactNode放入一組 StickyRevealItem
mediaSide"left" | "right""right"視覺區位置(左文右圖或左圖右文)
stickyTopnumber24吸頂視覺框距容器頂端的偏移(px)
activeIndexnumber受控模式:由外部指定作用段落索引
onActiveChange(index: number) => void作用段落改變時觸發
containerRefObject<HTMLElement | null>巢狀捲動容器 ref;省略則以視窗為準
showProgressbooleantrue顯示可點擊的段落進度圓點
stepClassNamestring"min-h-[70vh]"每段文字容器的 class(撐開捲動距離)
mediaClassNamestring吸頂視覺框的 class(覆寫比例、圓角等)
classNamestring根容器的 class

StickyRevealItem

Prop型別預設值說明
mediaReactNode對照顯示的視覺內容(圖片或圖形)
childrenReactNode隨捲動流動的文字內容
classNamestring附加到該段文字容器的 class

細節

  • 採用 IntersectionObserver 監看每段文字,以捲動容器「中央細帶」判定作用段落,單一時刻只有一段作用。
  • 所有 media 疊放在同一個吸頂框內,作用者淡入、非作用者淡出並帶輕微縮放與模糊,形成交叉揭示。
  • 受控/非受控雙模式:未傳 activeIndex 時內部自管狀態;傳入則由你掌控,捲動仍會透過 onActiveChange 回報。
  • StickyRevealItem 僅作宣告,實際佈局由 StickyReveal 讀取其 props 統一渲染,以便集中管理吸頂與交叉切換。
  • 可用 useStickyReveal() 在子樹中讀取 active / total / isStatic,打造自訂進度指示。

可及性

  • 尊重 prefers-reduced-motion:停用交叉淡入的過渡與模糊、進度圓點過渡,點擊定位改為即時跳轉;版面(吸頂)維持不變。
  • 非作用中的視覺層標記 aria-hidden,避免輔助科技重複朗讀。
  • 進度圓點為原生 <button>,可鍵盤聚焦與觸發,作用中者帶 aria-current,點擊平滑捲回該段。
  • 附帶 aria-live="polite" 區域即時播報「目前第 N 段,共 M 段」。

On this page