資料視覺敘事

堆疊長條圖

多層堆疊長條圖 React 元件:點擊圖例收合某一層,其餘層以彈簧下沉補位、Y 軸刻度同步重算並補間,hover 或方向鍵檢視該欄各層數值與占比。

把每一欄拆成多層來看組成的長條圖。頂部圖例每層一顆切換按鈕(色點、名稱、全期合計),點一下該層高度收合到 0 並淡出,上方各層以彈簧下沉補位;Y 軸依目前可見層的最大堆疊和重新取整,格線同步滑到新位置、刻度數字補間到新值。滑過某欄時其餘欄淡到一半,tooltip 依堆疊順序由上而下列出各層數值與占比。純 SVG 自繪、不依賴圖表函式庫,寬度跟隨容器。

把這個效果裝進你的專案

在專案資料夾執行指令,CLI 會加入原始碼與依賴套件,再依下方使用範例引用元件。

npx webberui@latest add stacked-column-chart

還沒有專案,或安裝遇到問題?看快速開始 →

Playground

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

300
260
600
編輯中的呼叫預設屬性
<StackedColumnChart/>

完整範例包含預覽的排版與資料。先安裝元件,再把範例檔貼入你的專案。

安裝

npx webberui@latest add https://webberui.com/r/stacked-column-chart.json

或在 components.json 設定 registries 後,改用 @webberui/stacked-column-chart 安裝。

使用

import { StackedColumnChart } from "@/components/ui/stacked-column-chart";

const series = [
  { key: "web", label: "官網" },
  { key: "store", label: "門市" },
  { key: "group", label: "團購" },
];

const data = [
  { label: "3 月", values: { web: 42, store: 31, group: 12 } },
  { label: "4 月", values: { web: 46, store: 29, group: 16 } },
  { label: "5 月", values: { web: 51, store: 33, group: 22 } },
];

<StackedColumnChart
  series={series}
  data={data}
  formatValue={(v) => `${v} 萬`}
  onHiddenKeysChange={(keys) => console.log("隱藏:", keys)}
/>

Props

Prop型別預設值說明
seriesStackedColumnSeries[]—層的定義,依序由下往上堆疊
dataStackedColumnDatum[]—每一欄的資料
hiddenKeysstring[]—受控的隱藏層 key;未提供時由元件內部管理
defaultHiddenKeysstring[][]非受控模式的初始隱藏層
onHiddenKeysChange(hiddenKeys: string[]) => void—隱藏層變動時回呼;元件保證至少保留一層可見
heightnumber300圖區高度(px,含 X 標籤),寬度跟隨容器
showTotalsbooleantrue是否在每欄頂端顯示可見層的總數
formatValue(value: number) => stringzh-TW 千分位數值格式化(軸、總數、tooltip 共用),貨幣與單位在這裡加
stiffnessnumber260彈簧剛性;提供時寫入 --wb-stacked-column-chart-stiffness
durationnumber600進場生長時長(ms);提供時寫入 --wb-stacked-column-chart-duration
ariaLabelstring"堆疊長條圖"圖表的無障礙名稱,用於摘要與資料表標題
classNamestring—透傳到最外層容器

StackedColumnSeries

欄位型別預設值說明
keystring—唯一識別碼,對應 data[].values 的鍵
labelstring—圖例與 tooltip 顯示名稱
colorstring—覆寫此層顏色;未提供時使用 --wb-stacked-column-chart-1 到 -5

StackedColumnDatum

欄位型別預設值說明
labelstring—X 軸標籤
valuesRecord<string, number>—各層數值,缺值或負數視為 0

另外具名匯出 niceStackedScale(max),回傳與圖表相同的 Y 軸上限與刻度,方便在外部對齊其他圖表。

細節

  • 配色走 CSS 變數:--wb-stacked-column-chart-1 到 -5 預設為 teal 由深到淺五階(#134e4a #0f766e #14b8a6 #5eead4 #ccfbf1),暗色模式自動換成較亮的一組;在任一祖先元素設定這五個變數即可整組覆寫,超過五層會循環使用。焦點框顏色讀 --wb-stacked-column-chart-accent(預設 #0d9488,暗色 #2dd4bf)。
  • 節奏也可外部覆寫:--wb-stacked-column-chart-stiffness(預設 260,阻尼固定 30)控制收合補位與格線移動的彈簧,--wb-stacked-column-chart-duration(預設 600ms)控制進場生長;欄與欄之間間隔 40ms,刻度數字補間 400ms。
  • 收合的層不會從 DOM 移除,而是高度歸零停在下方堆疊的頂端;重新展開時就從那個位置長出來,視覺上始終維持堆疊順序。
  • 至少保留一層可見:只剩一層時該圖例按鈕設定 aria-disabled,點擊不會隱藏;受控模式傳入「全部隱藏」時第一層仍會顯示。
  • 進場在圖表捲進畫面(useInView,邊界 -10%)時才觸發,且只播一次;tooltip 固定寬度並夾在容器內,不會溢出卡片。

可及性

  • 圖例是原生 button,以 aria-pressed 表示該層是否可見,Enter/空白鍵切換
  • 圖區可聚焦(tabIndex=0),←/→ 逐欄移動、Home/End 跳到首尾、Esc 收起 tooltip;目前欄的組成會透過 aria-live 區域朗讀
  • SVG 帶 role="img" 與包含欄數、可見層與最高合計的 aria-label 摘要,另附螢幕閱讀器專用的完整資料表(每欄、每層數值與可見層合計)
  • 可聚焦元素都有 focus-visible 焦點框
  • 使用者系統開啟「減少動態效果」時,整欄生長、層的收合補位與刻度補間都直接顯示終態,tooltip 仍可正常使用