WebberUI

Callout Stat Hero

以單一巨型數字撐滿首屏的 hero 版面,SVG 引導線隨捲動逐條描繪,將數字各部位連向周邊註解卡並依序浮現。

載入預覽⋯

Playground

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

<CalloutStatHero />

安裝

npx shadcn@latest add https://webberui.com/r/callout-stat-hero.json

或在 components.json 設定 registries 後,改用 @webberui/callout-stat-hero 安裝。

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

npm install motion clsx tailwind-merge

使用

import { CalloutStatHero } from "@/components/ui/callout-stat-hero";

<CalloutStatHero
  eyebrow="2025 客戶滿意度"
  value="94%"
  caption="推薦我們的受訪客戶比例"
  annotations={[
    { x: 8, y: 34, side: "left", title: "連續 5 季成長" },
    { x: 20, y: 76, side: "left", title: "12,480 份回饋" },
    { x: 92, y: 30, side: "right", title: "NPS 62" },
    { x: 82, y: 78, side: "right", title: "首次回應 < 2h" },
  ]}
/>

預設以整個視窗為捲動容器(h-screen 舞台)。若放進巢狀的 overflow-y-auto 容器,請把該容器的 ref 傳給 container,並用 stageClassName 覆寫舞台高度為容器可視高度:

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

<div ref={scrollerRef} className="h-[480px] overflow-y-auto">
  <CalloutStatHero
    value="94%"
    annotations={annotations}
    container={scrollerRef}
    stageClassName="h-[480px]"
  />
</div>

Props

Prop型別預設值說明
valueReact.ReactNode撐滿首屏的巨型數字
eyebrowReact.ReactNode數字上方的小標籤
captionReact.ReactNode數字下方的說明文字
annotationsStatAnnotation[]環繞數字的註解清單,捲動時依序描繪並浮現
connector"straight" | "elbow""straight"引導線樣式:直線或帶水平引入段的折線
scrollScalenumber依註解數估算捲動軌道高度為釘住舞台高度的倍數
offsetTopnumber0釘住舞台的吸頂位置(px)
containerRefObject<HTMLElement | null>巢狀捲動容器的 ref;預設以視窗為捲動容器
stageClassNamestring"h-screen"釘住舞台容器的 class;巢狀捲動時覆寫為容器可視高度
numberClassNamestring覆寫巨型數字的 class(字級、字重、顏色…)
aria-labelstring"數據主視覺"整個區塊的無障礙名稱

StatAnnotation

欄位型別預設值說明
xnumber錨點的水平位置(數字框寬度百分比,0–100)
ynumber錨點的垂直位置(數字框高度百分比,0–100)
titleReact.ReactNode註解卡標題
descriptionReact.ReactNode註解卡內文(可選)
side"left" | "right"x 自動判定卡片停靠左或右邊欄
idstring索引自訂 React key

細節

  • 區塊以 position: sticky 釘住整個舞台,外層軌道高度依 scrollScale 撐開,捲動距離即為引導線逐條描繪的進度來源。
  • 引導線的端點在掛載後量測 DOM(卡片內緣中點 → 數字錨點),以 ResizeObserver 追蹤重排,換算為舞台座標繪製,因此文字始終銳利、不會被縮放模糊。
  • 引線以 pathLength 描繪,錨點小圓在該條引線描完後才彈入,註解卡則以透明度與微幅位移浮現,形成「描線 → 亮點 → 出卡」的節奏。
  • x / y 是相對於數字元素邊界框的百分比,可精準指向某個字元或角落;靠近 0100 的錨點請預留邊距,避免被 overflow-hidden 舞台裁切。

可及性

  • 開啟系統「減少動態效果」時,改渲染不含捲動與引導線的靜態摘要:巨型數字加上依序編號的註解列表,資訊完整可讀。
  • 引導線 svg、錨點與起點小圓皆標記 aria-hidden,不干擾輔助科技;數字與註解文字維持正常朗讀。
  • 舞台容器帶 role="group"aria-label,可作為單一可辨識的區塊被導覽。

On this page