WebberUI

Case Study Dossier

卷宗式案例研究版面:左側 sticky 指標欄隨長文滾動逐一點亮並計數,全幅引言定期打斷雙欄節奏形成呼吸感。

載入預覽⋯

Playground

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

24
<CaseStudyDossier />

安裝

npx shadcn@latest add https://webberui.com/r/case-study-dossier.json

或在 components.json 設定 registries 後,改用 @webberui/case-study-dossier 安裝。

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

npm install motion clsx tailwind-merge

使用

CaseStudyDossier 包住若干 DossierSection,每節可綁定一個 metricDossierQuote 為打斷雙欄節奏的全幅引言。左側指標欄由各章節的 metric 自動生成,捲動到對應章節時該指標點亮並由 0 滾動計數。

import {
  CaseStudyDossier,
  DossierSection,
  DossierQuote,
} from "@/components/ui/case-study-dossier";

<CaseStudyDossier eyebrow="案例研究" title="Northwind 導入成效">
  <DossierSection
    id="roi"
    eyebrow="財務影響"
    title="投資報酬率"
    metric={{ label: "投資報酬率", value: 320, suffix: "%" }}
    accentClassName="text-emerald-600 dark:text-emerald-400"
  >
    <p>以十二個月為期計算,平台帶來的節省合計達初始投入的 3.2 倍。</p>
  </DossierSection>

  <DossierQuote cite="Ada Lin,營運長">
    資料在早餐前就已經到位,團隊得以把時間投回真正的決策。
  </DossierQuote>

  <DossierSection
    id="retention"
    title="淨收入留存率"
    metric={{ label: "淨收入留存", value: 118, suffix: "%" }}
  >
    <p>更快的服務回應與更精準的續約提醒,讓留存率提升至 118%。</p>
  </DossierSection>
</CaseStudyDossier>

若版面置於巢狀捲動容器(overflow-y-auto)內,將容器的 ref 傳給 container,並視情況把 stickyTop 調小:

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

<div ref={scrollerRef} className="h-[420px] overflow-y-auto">
  <CaseStudyDossier container={scrollerRef} stickyTop={8}>
    {/* … */}
  </CaseStudyDossier>
</div>

Props

CaseStudyDossier

Prop型別預設值說明
childrenReact.ReactNode放入 DossierSectionDossierQuote
containerRefObject<HTMLElement | null>巢狀捲動容器的 ref;預設以視窗為捲動容器
eyebrowReact.ReactNode指標欄頂端小標
titleReact.ReactNode指標欄標題
labelstring"案例指標"指標欄 <aside> 的無障礙標籤
stickyTopnumber24sticky 指標欄距捲動容器頂端的偏移(px)

DossierSection

Prop型別預設值說明
idstring章節錨點 id,指標點擊與觀察器以此對應
titlestring章節標題
eyebrowReact.ReactNode標題上方分類小標
metricDossierMetric綁定此章節的指標數字
accentClassNamestring指標為當前章節時,數字的強調文字色 class

DossierMetric

欄位型別預設值說明
labelstring指標說明
valuenumber目標數值,由 0 滾動計數至此
prefixstring""數字前綴,如 "$"
suffixstring""數字後綴,如 "%""×"
decimalsnumber0小數位數

DossierQuote

Prop型別預設值說明
childrenReact.ReactNode引言內容
citeReact.ReactNode引言出處

細節

  • 指標欄以 IntersectionObserver 取各章節可見比例,最高者為「當前章節」; 當前及其之前的指標視為已抵達(點亮)。
  • 每個指標以 MotionValue 逐格更新計數,不觸發 React re-render;首次抵達 該章節時由 0 計數至目標值。
  • 全幅引言(DossierQuote)在寬容器下以負邊距回收左側指標欄空間,橫跨整個 版面以打斷雙欄節奏。
  • 左側指標欄使用 @container 查詢,窄容器(< 34rem)時收合,並改由各章節 就地顯示其指標。

可及性

  • 指標欄為 <aside> 並帶無障礙標籤;每個指標為可聚焦按鈕,點擊平滑捲動至 對應章節,aria-label 完整朗讀「章節,指標 值」。
  • 計數中的動畫數字對輔助科技隱藏(aria-hidden),朗讀時為最終值。
  • 當前章節與其對應指標標記 aria-current
  • 使用者系統開啟「減少動態效果」時,數字直接顯示最終值不做計數,引言與 內文的浮出動畫停用,指標點亮改為即時切換。

On this page