Linked Bars
three.jsA table and a 3D bar chart that share one highlight.
Install
$ npx shadcn@latest add https://spotcheckui.com/r/linked-bars.jsonAlso installs three, @react-three/fiber.
Usage
"use client"
import dynamic from "next/dynamic"
const LinkedBars = dynamic(
() => import("@/components/spotcheck/linked-bars").then((module) => module.LinkedBars),
{ ssr: false },
)
<LinkedBars
title="Requests per week, in thousands"
rows={["Mumbai", "Frankfurt", "Oregon"]}
columns={["W1", "W2", "W3"]}
values={[
[14, 18, 21],
[22, 24, 23],
[31, 29, 34],
]}
format={(value) => value.toFixed(1)}
/>The table is real table markup with every value in it, so nobody needs the chart to read the data. On a narrow screen the table scrolls inside its own box, and the chart sits above it.
Highlighting
Hovering or focusing a row raises its bars in the accent and dims the rest. Hovering a bar does the same for its row and shows a tooltip. On touch, tap a row or a bar to set the highlight, tap the row again to clear it, or tap the empty part of the chart.
To drive the highlight from outside, pass highlight and onHighlightChange. Use null for no
highlight. Rows and bars are counted from 0.
Props
- title
stringDefault —Printed above the table, and names it for screen readers. - rows * Required
string[]Default —Row names, in the same order as `values`. - columns * Required
string[]Default —Column names, in the same order as each row of `values`. - values * Required
number[][]Default —One array per row, holding one number per column. - label
stringDefault Built inDescribes the chart for screen readers. - highlight
number | nullDefault —The highlighted row, when you control it. Use `null` for no highlight. - onHighlightChange
(row: number | null) => voidDefault —Runs when the highlighted row changes. - format
(value: number) => stringDefault (value) => String(value)Formats each value. Pass it from a client component.
Keyboard
| Tab | Move between rows, which highlights each one in the chart |
|---|---|
| Enter | Keep the row highlighted after focus moves on |
Reduced motion
Bars jump to their new height, and the chart renders one frame per change.