KPI 迷你趨勢卡
數值滾動進場、內嵌 sparkline 折線與漲跌徽章的指標卡。
儀表板常用的 KPI 指標卡:進入視窗時大數字由 0 滾動累加、SVG sparkline 以描邊動畫畫出趨勢曲線並淡入線下漸層,右上角彈出綠升紅降的百分比徽章,卡片依序 stagger 進場。
把這個效果裝進你的專案
在專案資料夾執行指令,CLI 會加入原始碼與依賴套件,再依下方使用範例引用元件。
npx webberui@latest add kpi-sparkline-cardsKPI Sparkline Cards 是用 React、Tailwind CSS、Motion 與 SVG 做的 KPI 指標卡(stat card)元件:每張卡片包含可滾動累加的大數字、以 SVG path 畫出的迷你趨勢圖(sparkline)和漲跌百分比徽章,卡片進入視窗時才播放進場動畫。
Playground
即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。
<KpiSparklineCards/>
完整範例包含預覽的排版與資料。先安裝元件,再把範例檔貼入你的專案。
適用情境
- SaaS 後台或管理介面的首頁儀表板,列出營收、訂閱數、轉換率等核心指標。
- 電商賣家後台的今日/本月銷售摘要。
- 行銷成效報告頁,搭配前期比較的漲跌幅。
- 產品官網展示「使用者成長」這類數據亮點區塊。
- 不適合:需要點擊指標展開明細時,改用 Drilldown Stat Grid。
安裝
npx webberui@latest add https://webberui.com/r/kpi-sparkline-cards.json或在 components.json 設定 registries 後,改用 @webberui/kpi-sparkline-cards 安裝。
使用
import { KpiSparklineCards } from "@/components/ui/kpi-sparkline-cards";
<KpiSparklineCards
items={[
{
label: "本月營收",
value: 1284500,
delta: 12.4,
prefix: "NT$",
series: [42, 48, 45, 52, 58, 63, 70, 76],
},
{
label: "轉換率",
value: 3.62,
delta: -1.8,
suffix: "%",
decimals: 2,
series: [52, 50, 47, 44, 41, 38],
},
]}
/>範例
從伺服器資料產生指標卡
KpiSparklineItem 型別可以直接拿來描述 API 回傳的資料;在 Server Component 中轉換好再傳給 items。
// app/dashboard/page.tsx
import {
KpiSparklineCards,
type KpiSparklineItem,
} from "@/components/ui/kpi-sparkline-cards";
import { getMetrics } from "@/lib/metrics";
export default async function DashboardPage() {
const m = await getMetrics(); // 例如 { revenue: { total, change, daily: number[] }, ... }
const items: KpiSparklineItem[] = [
{ label: "本月營收", value: m.revenue.total, delta: m.revenue.change, prefix: "NT$", series: m.revenue.daily },
{ label: "付費訂閱", value: m.subscribers.total, delta: m.subscribers.change, series: m.subscribers.daily },
{ label: "平均客單價", value: m.aov.total, delta: m.aov.change, prefix: "NT$", series: m.aov.daily },
];
return <KpiSparklineCards items={items} className="xl:grid-cols-3" />;
}小數位數與單位
decimals 控制小數位數,prefix/suffix 加上貨幣符號或單位;delta 為 0 時徽章與折線顯示中性灰。
<KpiSparklineCards
items={[
{ label: "轉換率", value: 4.28, delta: 0.6, suffix: "%", decimals: 2, series: [3.1, 3.4, 3.6, 3.9, 4.0, 4.28] },
{ label: "平均回應時間", value: 182, delta: -8.5, suffix: " ms", series: [240, 226, 210, 198, 190, 182] },
{ label: "NPS", value: 46, delta: 0, series: [45, 47, 46, 44, 46, 46] },
]}
/>調整欄數與動畫節奏
外層是 sm:grid-cols-2 xl:grid-cols-4 的網格,className 會用 cn 合併,可以覆寫欄數與間距。countDuration、drawDuration 與 stagger 分別控制數字累加、折線描繪與卡片依序進場的秒數。
<KpiSparklineCards
items={items}
className="gap-6 lg:grid-cols-2 xl:grid-cols-2"
countDuration={2}
drawDuration={1.6}
stagger={0.2}
/>Props
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
items | KpiSparklineItem[] | — | KPI 指標卡的資料清單 |
countDuration | number | 1.4 | 大數字滾動累加的時長(秒) |
drawDuration | number | 1.1 | sparkline 描邊動畫的時長(秒) |
stagger | number | 0.12 | 卡片依序進場的間隔(秒) |
className | string | — | 透傳到外層網格容器 |
KpiSparklineItem 欄位:
| 欄位 | 型別 | 預設值 | 說明 |
|---|---|---|---|
label | string | — | 指標名稱,顯示於卡片左上角 |
value | number | — | 指標數值,進場時由 0 滾動累加至此值 |
delta | number | — | 相較前期的漲跌百分比:正值綠色、負值紅色、0 為中性灰 |
series | number[] | — | 迷你趨勢折線的資料數列(建議至少 6 個點) |
prefix | string | — | 數值前綴,例如 "NT$" |
suffix | string | — | 數值後綴,例如 "%" |
decimals | number | 0 | 數值顯示的小數位數 |
可及性
- 使用者系統開啟「減少動態效果」時,數字直接顯示最終值、折線立即完整呈現,不播放滾動與描邊動畫
- 每張卡片提供
sr-only完整摘要(指標名稱、最終數值與漲跌方向),動畫中的數字與 sparkline 對輔助科技隱藏(aria-hidden),避免朗讀跳動中的過渡值 - 漲跌不單靠顏色傳達:徽章同時以箭頭方向圖示與文字百分比表達趨勢
- 大數字使用
tabular-nums,滾動累加過程中版面寬度穩定不抖動
常見問題
可以在 Next.js App Router 的 Server Component 使用嗎?
可以。元件檔案開頭已有 "use client",Server Component 頁面可以直接 import 並傳入 items,items 只包含字串、數字與數字陣列,可以從伺服器序列化傳入。數字首次渲染固定為 0,伺服器與用戶端輸出一致,不會有 hydration 不符的問題。
數字是怎麼格式化的?
數字會加上千分位:中文版元件使用 Intl.NumberFormat("zh-TW"),英文版使用 Intl.NumberFormat("en-US"),小數位數由每個項目的 decimals 決定(預設 0)。
數值下降一定是紅色嗎?跳出率這類越低越好的指標怎麼辦?
顏色只看 delta 的正負:正值綠色、負值紅色、0 灰色,沒有反轉顏色的 prop。越低越好的指標需要直接修改原始碼中的 tone 判斷,或在 label 中說明方向。
資料更新時會重新播放動畫嗎?
卡片的進場與描邊只在第一次進入視窗時播放(useInView 搭配 once: true)。之後若 value 改變,大數字會重新從 0 累加到新值。
有支援減少動態效果與螢幕報讀器嗎?
系統開啟「減少動態效果」時數字直接顯示最終值,折線與徽章立即呈現。每張卡片有一段 sr-only 摘要讀出名稱、最終數值與漲跌方向,動畫中的數字對輔助科技隱藏。依賴為 motion、lucide-react、clsx 與 tailwind-merge。