WebberUI

Leading Unfold

行距展開敘事:整段文字初始壓縮成近乎實心的墨塊,捲動進度驅動行距與字距逐步攤展為可讀段落,版面高度隨之生長並推移後續區塊。

載入預覽⋯

Playground

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

0.32
1.75
-0.055
3
<LeadingUnfold />

安裝

npx shadcn@latest add https://webberui.com/r/leading-unfold.json

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

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

npm install motion clsx tailwind-merge

使用

import { LeadingUnfold } from "@/components/ui/leading-unfold";

<LeadingUnfold className="text-lg font-medium">
  整段文字初始壓縮成一塊墨團,隨著捲動逐步攤展成可讀段落。
</LeadingUnfold>

元件以自身在捲動容器中的位置建立 useScroll,隨著頂緣進入設定的觸發區間,line-heightletter-spacing 由壓縮狀態插值到展開狀態。若文字位於巢狀的 overflow 捲動容器內,請把容器 ref 傳入 container

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

<div ref={scrollerRef} className="h-[300px] overflow-y-auto">
  <LeadingUnfold container={scrollerRef}>{longText}</LeadingUnfold>
</div>

受控模式

傳入外部的 progress(一個 0 → 1MotionValue)即可自行驅動展開,例如綁定到頁面級的 useScroll 或任意動畫來源:

const { scrollYProgress } = useScroll();

<LeadingUnfold progress={scrollYProgress}>{longText}</LeadingUnfold>

Props

Prop型別預設值說明
childrenReact.ReactNode要展開的整段文字
compressedLeadingnumber0.32壓縮狀態的行距倍率,越小越重疊成墨塊
expandedLeadingnumber1.75展開狀態(最終可讀段落)的行距倍率
compressedTrackingnumber-0.055壓縮狀態的字距(em),負值加強墨塊感
expandedTrackingnumber0展開狀態的字距(em)
blurbooleantrue壓縮時是否附帶輕微模糊,展開過程中散去
blurAmountnumber3壓縮狀態的最大模糊半徑(px)
offsetScrollOffset["start 0.85", "start 0.4"]覆寫 useScroll 觸發區間
progressMotionValue<number>受控模式:外部傳入 0→1 進度驅動展開
containerRefObject<HTMLElement | null>巢狀捲動容器 ref;預設以視窗為捲動容器
as"p" | "div" | "blockquote" | "h2" | "h3""p"渲染的語意標籤
classNamestring附加樣式(字級、字重、顏色等)

細節

  • 觸發區間兩端都以區塊的頂緣(start)為錨點,因此文字向下生長的底緣不會回頭干擾自身的進度計算,展開過程平順、單向。
  • 動畫 line-height 會逐幀觸發回流,這正是「版面高度隨之生長並推移後續區塊」效果的來源;建議每個視圖只用在少量的敘事區塊上。
  • 字級、字重與顏色皆交由 className 控制,元件本身只負責行距、字距與模糊的插值。

可及性

  • 文字為真實 DOM 節點,壓縮狀態僅是視覺樣式,螢幕閱讀器始終讀到完整、正確的段落。
  • 使用者系統開啟「減少動態效果」時,直接以展開狀態靜態渲染最終可讀段落,不掛載任何捲動動畫。

On this page