Chart Utils

Shared helpers for building and styling your own charts.

Bookings
Orders
Bills
Refunds
Other
1.3M · 42.1%

Installation

pnpm dlx shadcn@latest add @paneui/chart-utils

Usage

Examples

Chart Number

Tooltip

Legend

Scales and Ticks

Motion

useChartTransition, ChartNumber and ChartTooltip all become instant under reduced motion.

Accessibility

ChartNumber keeps the final value in a screen-reader-only span, ChartTooltip is a polite live region, and ChartDataTable renders an sr-only table mirror of a chart's data.

API Reference

ChartNumber

Number that springs between values. Also accepts every prop of span.

value*
number
Value to show.
format= formatNumber
(value: number) => string
Formatter applied to every frame.
PropTypeDefaultDescription
value*number—Value to show.
format(value: number) => stringformatNumberFormatter applied to every frame.

ChartTooltip

In-chart floating surface that follows a data point. Place it inside a positioned chart container; no portal. Also accepts every prop of motion.div.

x*
number
Anchor x in px, relative to the chart container.
y*
number
Anchor y in px.
open*
boolean
Show or hide the tooltip.
bounds*
{ width: number; height: number }
Container size, used to keep the tooltip inside it.
side= "top"
"top" | "bottom" | "left" | "right"
Preferred side.
offset= 12
number
Gap from the anchor in px.
avoidCollisions= true
boolean
Flip to the opposite side when the preferred side leaves the bounds.
PropTypeDefaultDescription
x*number—Anchor x in px, relative to the chart container.
y*number—Anchor y in px.
open*boolean—Show or hide the tooltip.
bounds*{ width: number; height: number }—Container size, used to keep the tooltip inside it.
side"top" | "bottom" | "left" | "right""top"Preferred side.
offsetnumber12Gap from the anchor in px.
avoidCollisionsbooleantrueFlip to the opposite side when the preferred side leaves the bounds.
data-side
The side actually used after flipping.
Data attributeDescription
data-sideThe side actually used after flipping.

ChartTooltipTitle

Also accepts every prop of div.

ChartTooltipRow

Also accepts every prop of div.

label*
ReactNode
Series name.
value*
ReactNode
Formatted value, right-aligned.
color
string
Swatch colour before the label.
PropTypeDefaultDescription
label*ReactNode—Series name.
value*ReactNode—Formatted value, right-aligned.
colorstring—Swatch colour before the label.

ChartSwatch

Also accepts every prop of span.

color*
string
CSS colour of the swatch.
PropTypeDefaultDescription
color*string—CSS colour of the swatch.

ChartLegend

Wrapping row of legend items. Also accepts every prop of div.

ChartLegendItem

Legend entry, rendered as a button. Also accepts every prop of button.

color*
string
Series colour.
inactive
boolean
Dimmed with a hollow swatch (series toggled off).
highlighted
boolean
Emphasised because the matching mark is hovered.
value
ReactNode
Optional trailing value (share, count…).
PropTypeDefaultDescription
color*string—Series colour.
inactiveboolean—Dimmed with a hollow swatch (series toggled off).
highlightedboolean—Emphasised because the matching mark is hovered.
valueReactNode—Optional trailing value (share, count…).
data-inactive
Present when inactive.
data-highlighted
Present when highlighted.
Data attributeDescription
data-inactivePresent when inactive.
data-highlightedPresent when highlighted.

ChartDataTable

Screen-reader-only table mirror of a chart. Takes no other props.

caption*
string
Table caption.
columns*
readonly string[]
Column headers.
rows*
readonly (readonly ReactNode[])[]
Rows; the first cell is the row header.
PropTypeDefaultDescription
caption*string—Table caption.
columns*readonly string[]—Column headers.
rows*readonly (readonly ReactNode[])[]—Rows; the first cell is the row header.

chartColor

chartColor(index) returns the series colour, --chart-1…8 first (each falls back to a semantic token), then blends for indexes past eight. CHART_COLORS holds the base eight.

index*
number
Series index.
PropTypeDefaultDescription
index*number—Series index.

chartAlpha

chartAlpha(color, percent) mixes a colour toward transparent for fills.

color*
string
Any CSS colour.
percent*
number
Opacity, 0–100.
PropTypeDefaultDescription
color*string—Any CSS colour.
percent*number—Opacity, 0–100.

onFill

onFill(fill) returns a readable label colour for text drawn on that fill, white on dark fills, near-black on light ones (CSS relative colour). Set it as the inline fill and keep a fill-white class as the fallback for browsers without relative colour. Used by treemap, candlestick and funnel labels.

fill*
string
The fill colour behind the label (any CSS colour or var(--token)).
PropTypeDefaultDescription
fill*string—The fill colour behind the label (any CSS colour or var(--token)).

scaleLinear

scaleLinear(domain, range) maps values to pixels; the result also has domain, range, invert(px) and ticks(count = 5).

domain*
readonly [number, number]
Input extent.
range*
readonly [number, number]
Output extent in px.
PropTypeDefaultDescription
domain*readonly [number, number]—Input extent.
range*readonly [number, number]—Output extent in px.

scaleBand

scaleBand(count, range, padding) returns the x of band i, plus bandwidth, step and indexAt(px).

count*
number
Number of bands.
range*
readonly [number, number]
Output extent in px.
padding= 0.2
number
Share (0–1) of each step left empty.
PropTypeDefaultDescription
count*number—Number of bands.
range*readonly [number, number]—Output extent in px.
paddingnumber0.2Share (0–1) of each step left empty.

niceDomain

niceDomain([lo, hi], count = 5) rounds a domain outward to tidy tick boundaries.

formatCompact / formatNumber / formatPercent

formatCompact(1284000) → 1.3M; formatNumber keeps up to 2 decimals; formatPercent(share, digits = 1) turns 0.42 into 42.0%. clamp(value, min, max) and seededRandom(seed), for deterministic demo data, are also exported.

useChartSize

const [ref, size] = useChartSize() observes an element's content box with ResizeObserver.

initial= { width: 0, height: 0 }
{ width: number; height: number }
Size before the first measure.
PropTypeDefaultDescription
initial{ width: number; height: number }{ width: 0, height: 0 }Size before the first measure.

useChartTransition

Returns the house chart spring (CHART_SPRING), or { duration: 0 } under reduced motion.

delay= 0
number
Delay in seconds.
PropTypeDefaultDescription
delaynumber0Delay in seconds.

useActiveId

const [active, setActive] = useActiveId(value, defaultValue, onChange) holds the controlled or uncontrolled active id shared by the charts.

controlled
T | null | undefined
Controlled value; undefined means uncontrolled.
defaultValue
T | null | undefined
Initial value when uncontrolled.
onChange
(id: T | null) => void
Called on every change.
PropTypeDefaultDescription
controlledT | null | undefined—Controlled value; undefined means uncontrolled.
defaultValueT | null | undefined—Initial value when uncontrolled.
onChange(id: T | null) => void—Called on every change.

useChartId

useChartId(prefix) returns a DOM-safe id for SVG defs.

useHoverCapable

true when the device matches (hover: hover), for hover-vs-tap tooltips.