Paste-Up Assembly
剪貼稿般散落的區塊,滾動進入時以 FLIP 飛回各自網格版位組成乾淨版面,反向滾動則重新散開。
載入預覽⋯
Playground
即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。
2
64
12
0.5
7
<PasteUpAssembly />
安裝
npx shadcn@latest add https://webberui.com/r/paste-up-assembly.json或在 components.json 設定 registries 後,改用 @webberui/paste-up-assembly 安裝。
安裝依賴後,從 registry JSON(/r/paste-up-assembly.json 的 files[0].content)複製 paste-up-assembly.tsx 原始碼到你的 components/ui/ 目錄:
npm install motion clsx tailwind-merge使用
每個直接子元素會成為一張「剪貼稿」。初始時各區塊隨機位移、旋轉、疊放,像散落在工作檯上的稿件;當版面被捲入釘住區間,所有元素依序飛回自己的網格版位,組成乾淨版面。反向捲動則重新散開。
import { PasteUpAssembly } from "@/components/ui/paste-up-assembly";
<PasteUpAssembly columns={3} gap={16}>
<div>剪貼稿 A</div>
<div>剪貼稿 B</div>
<div>剪貼稿 C</div>
<div>剪貼稿 D</div>
<div>剪貼稿 E</div>
<div>剪貼稿 F</div>
</PasteUpAssembly>;若滾動發生在巢狀的 overflow 容器內,把該容器的 ref 傳給 container:
const scrollerRef = React.useRef<HTMLDivElement>(null);
<div ref={scrollerRef} className="h-[300px] overflow-y-auto">
<PasteUpAssembly container={scrollerRef} stickyTop={12} travel={340}>
{/* ... */}
</PasteUpAssembly>
</div>;Props
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
children | React.ReactNode | — | 每個直接子元素成為一張剪貼稿 |
columns | number | 3 | 網格欄數 |
gap | number | 16 | 網格間距(px) |
scatter | number | 96 | 散落半徑(px),越大散得越開、疊得越亂 |
rotate | number | 10 | 散落時的最大旋轉角度(deg) |
scaleFrom | number | 0.9 | 散落時的縮放起點(0–1) |
stagger | number | 0.5 | 各件組裝時間窗錯開程度(0 同時歸位、1 完全依序) |
travel | number | 600 | 釘住期間可捲動的距離(px) |
stickyTop | number | 0 | 版面釘住時距離捲動容器頂端的位置(px) |
decoration | "tape" | "pin" | "none" | "tape" | 每張剪貼稿的裝飾樣式 |
seed | number | 1 | 散落亂數種子,改變它得到不同散落佈局(SSR 穩定) |
container | React.RefObject<HTMLElement | null> | — | 巢狀捲動容器的 ref;預設以視窗為捲動容器 |
className | string | — | 套用在最外層容器 |
itemClassName | string | — | 套用在每張剪貼稿外層(承載變換) |
細節
- 組裝以捲動進度驅動(scrub),並非一次性播放,所以來回捲動時區塊會可逆地聚合與散開。
- 網格提供每張剪貼稿的最終位置(Last),散落狀態只是相對版位的變換位移(invert),因此無需量測 DOM 即可達到 FLIP 的視覺效果。
- 散落佈局由
seed搭配確定性亂數產生,伺服器端與客戶端輸出一致,不會有 hydration 落差;換一個seed即可得到全新的散落排布。 - 各件的組裝時間窗集中在釘住區間中段並依
stagger錯開,看起來像稿件被逐張貼回版面。 travel決定釘住期間的捲動距離;巢狀容器內請把travel調小以配合較短的捲動高度。
可及性
- 使用者系統開啟「減少動態效果」(
prefers-reduced-motion)時,直接渲染對位後的乾淨網格,不做散落與釘住捲動。 - 內容維持在 DOM 的自然順序,散落只是視覺變換,不影響朗讀順序與 Tab 焦點次序。
- 膠帶/圖釘等裝飾皆標註
aria-hidden並停用指標事件,不干擾互動與輔助科技。