Components Advanced
ChartContainer
BetaAn accessible chart frame with title, legend, responsive sizing and a data-table alternative.
ChartContainer is not a charting engine. It gives any chart a consistent frame: a title and description, a legend using the theme-aware chart colours, the measured width for responsive drawing, and a “View as table” toggle so the data is never locked inside graphics. Stance includes two small SVG charts built on it: BarChart and Sparkline.
Overview
Signature deployments are accelerating
Mailboxes updated each month through the Exchange relay.
- Deployed
- Failed
import { BarChart } from '@bindshq/stance-react';
const deployments = [
{ month: 'Jun', deployed: 120, failed: 9 },
{ month: 'Jul', deployed: 164, failed: 7 },
{ month: 'Aug', deployed: 151, failed: 12 },
{ month: 'Sep', deployed: 238, failed: 5 },
{ month: 'Oct', deployed: 260, failed: 4 },
{ month: 'Nov', deployed: 302, failed: 3 },
];
export function Bars() {
return (
<BarChart
title="Signature deployments are accelerating"
description="Mailboxes updated each month through the Exchange relay."
data={deployments}
categoryKey="month"
categoryLabel="Month"
series={[
{ key: 'deployed', label: 'Deployed' },
{ key: 'failed', label: 'Failed' },
]}
/>
);
}Light, dark and high contrast
Every Stance component is designed and tested in all three appearance modes.
Signature deployments are accelerating
Mailboxes updated each month through the Exchange relay.
- Deployed
- Failed
Signature deployments are accelerating
Mailboxes updated each month through the Exchange relay.
- Deployed
- Failed
Signature deployments are accelerating
Mailboxes updated each month through the Exchange relay.
- Deployed
- Failed
Import
import { ChartContainer, BarChart, Sparkline } from '@bindshq/stance-react';Examples
Custom chart
Use the render function to draw your own SVG with the measured size and series colours.
Deployed mailboxes
- Deployed
import { ChartContainer } from '@bindshq/stance-react';
const deployments = [
{ month: 'Jun', deployed: 120, failed: 9 },
{ month: 'Jul', deployed: 164, failed: 7 },
{ month: 'Aug', deployed: 151, failed: 12 },
{ month: 'Sep', deployed: 238, failed: 5 },
{ month: 'Oct', deployed: 260, failed: 4 },
{ month: 'Nov', deployed: 302, failed: 3 },
];
export function Custom() {
const values = deployments.map((d) => d.deployed);
const max = Math.max(...values);
return (
<ChartContainer
title="Deployed mailboxes"
series={[{ key: 'deployed', label: 'Deployed' }]}
data={deployments}
categoryKey="month"
height={180}
>
{({ width, height, colors }) => {
const step = width / (values.length - 1);
const points = values
.map((v, i) => `${i * step},${height - 8 - (v / max) * (height - 16)}`)
.join(' ');
return (
<svg
width={width}
height={height}
role="img"
aria-label="Line chart: deployed mailboxes rose from 120 in June to 302 in November."
>
<polyline
points={points}
fill="none"
stroke={colors[0]}
strokeWidth={2}
strokeLinejoin="round"
/>
</svg>
);
}}
</ChartContainer>
);
}Sparkline
Word-sized trends for stat cards and tables, with a generated text summary.
import { Sparkline } from '@bindshq/stance-react';
export function Sparklines() {
return (
<div style={{ display: 'grid', gap: 16 }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
<span style={{ width: 160 }}>Active signatures</span>
<Sparkline data={[42, 48, 51, 49, 60, 72, 81]} />
</div>
<div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
<span style={{ width: 160 }}>Failed deliveries</span>
<Sparkline data={[12, 9, 11, 7, 5, 4, 3]} area color="var(--st-color-chart-3)" />
</div>
</div>
);
}API reference
ChartContainer
| Prop | Type | Default | Description |
|---|---|---|---|
title* required | ReactNode | None | Visible title; names the figure. |
description | ReactNode | None | What the chart shows; linked with aria-describedby. |
series | ChartSeries[] | None | { key, label, color? } per series. Colours default to --st-color-chart-1…5. |
data | ChartDatum[] | None | Rows for the data table alternative. |
categoryKey | string | None | Key of the category column in data. |
categoryLabel | string | 'Category' | Header of the category column. |
height | number | 240 | Chart area height in px. |
children* required | ReactNode | ({ width, height, colors }) => ReactNode | None | The chart, or a render function receiving the measured size. |
formatValue | (value: number, series) => string | None | Formats values in the table. |
showLegend | boolean | None | Defaults to true when there are series. |
defaultView | 'chart' | 'table' | 'chart' | Initial view. |
actions | ReactNode | None | Extra header controls, such as a period selector. |
headingLevel | 2 | 3 | 4 | 5 | 6 | 3 | Title heading level. |
BarChart
| Prop | Type | Default | Description |
|---|---|---|---|
data / categoryKey / series* required | ChartDatum[] / string / ChartSeries[] | None | Grouped vertical bars per category. |
maxValue | number | None | Fixed axis maximum; defaults to a rounded data maximum. |
summary | string | None | Overrides the generated accessible summary. |
Sparkline
| Prop | Type | Default | Description |
|---|---|---|---|
data* required | number[] | None | Values, oldest first. |
width / height | number | 120 / 32 | Size in px. |
area | boolean | false | Fill under the line. |
color | string | 'var(--st-color-chart-1)' | Line colour. |
label | string | null | None | Overrides the generated summary; null hides it when adjacent text describes the trend. |
Accessibility
- The container is a <figure> named by its title and described by its description.
- BarChart and Sparkline render role="img" with a generated summary, such as “Highest: Deployed in Sep, 260”.
- “View as table” replaces the chart with a real data table, the most reliable way for screen reader users to explore values.
- Chart colours come from the ink ramp and adapt to each theme. Pair colour with labels; never rely on colour alone.
Keyboard
| Keys | Action |
|---|---|
| Enter Space | Toggles between chart and table views. |
Usage guidelines
Do
- Write a title that states the insight, not just the metric.
- Always provide data for the table alternative.
Don’t
- Use more than five series in one chart.
- Use charts where a single number in a StatCard would do.