Chart composition
Chart layout chrome, legends, stats rows, and configuration utilities
Compose chart types from Chart components with wrappers and helpers. ChartContainer adds title, loading, and empty states; ChartStatsFooter and DetailLegend add summary rows and rich legends (for example LineChartCard).
Prerequisites
Components
| Component | Description |
|---|---|
ChartContainer | Wrapper for charts with title and loading states |
MinMaxAvg | Min / max / avg summary row |
ChartContainer
Wrapper for charts with loading and empty states.
Import
import { ChartContainer } from '@tetherto/mdk-react-devkit/core'Props
| Prop | Status | Type | Default | Description |
|---|---|---|---|---|
children | Required | ReactNode | none | Chart body (for example a BarChart or LineChart) |
title | Optional | string | none | Title text |
header | Optional | ReactNode | none | Custom header node |
legendData | Optional | LegendItem[] | none | Legend entries rendered in the container chrome |
highlightedValue | Optional | object | none | Highlighted metric (value, optional unit, className, style); highlight chrome renders only when this prop is set and the chart body is visible (not loading / not empty) |
rangeSelector | Optional | object | none | Range selector props (options, value, onChange, optional className, style, buttonClassName) |
loading | Optional | boolean | none | When true, shows a centered Loader overlay over the chart area |
empty | Optional | boolean | none | When true, shows empty state |
emptyMessage | Optional | string | 'No data available' | Copy shown in the empty overlay when empty is true and loading is not true |
minMaxAvg | Optional | object | none | Min / max / avg strings for the summary row |
timeRange | Optional | string | none | Time range label |
footer | Optional | ReactNode | none | Footer slot |
footerClassName | Optional | string | none | Class name on the footer wrapper |
onToggleDataset | Optional | function | none | Called with dataset index when legend toggles visibility |
className | Optional | string | none | Root class name from the host app |
Basic usage
<ChartContainer loading={isLoading} empty={data.length === 0}>
<BarChart data={data} />
</ChartContainer>ChartStatsFooter
Import
import { ChartStatsFooter } from '@tetherto/mdk-react-devkit/core'Props
| Prop | Status | Type | Default | Description |
|---|---|---|---|---|
minMaxAvg | Optional | object | none | Min, max, and average strings shown in the primary row when provided |
stats | Optional | ChartStatsFooterItem[] | none | Additional stat rows (label, value) in a columnar grid |
statsPerColumn | Optional | number | 1 | Number of stat items per column when stats is set |
secondaryLabel | Optional | object | none | Secondary block with title and value when provided |
className | Optional | string | none | Root class name from the host app |
The component renders nothing when minMaxAvg, stats, and secondaryLabel are all absent or empty.
Basic usage
<ChartStatsFooter
stats={[
{ label: 'Min', value: '120 TH/s' },
{ label: 'Max', value: '180 TH/s' },
{ label: 'Avg', value: '150 TH/s' },
]}
/>DetailLegend
Import
import { DetailLegend } from '@tetherto/mdk-react-devkit/core'Props
| Prop | Status | Type | Default | Description |
|---|---|---|---|---|
items | Required | DetailLegendItem[] | none | Legend rows (label, color, optional icon, currentValue, percentChange, hidden) |
onToggle | Optional | function | none | Called with label and index when a row is toggled |
className | Optional | string | none | Root class name from the host app |
Basic usage
<DetailLegend
items={[
{ label: 'Online', color: '#72F59E', currentValue: { value: 85, unit: '%' } },
{ label: 'Offline', color: '#FF6B6B', currentValue: { value: 15, unit: '%' } },
]}
/>MinMaxAvg
Compact row displaying min, max, and average values with consistent MDK label and value styling. Rendered by ChartContainer and ChartStatsFooter when their minMaxAvg prop is set; also usable standalone.
Compact summary row displaying min, max, and average values with consistent MDK label and value styling. Rendered automatically by ChartContainer when its minMaxAvg prop is set, and by ChartStatsFooter in the same way. Use it directly when you need the summary row outside of a ChartContainer or ChartStatsFooter.
The component renders nothing when all three values are absent or empty strings.
Import
import { MinMaxAvg } from '@tetherto/mdk-react-devkit/core'
import type { MinMaxAvgProps, MinMaxAvgValues } from '@tetherto/mdk-react-devkit/core'Props
| Prop | Status | Type | Default | Description |
|---|---|---|---|---|
min | Optional | string | none | Minimum value label (for example '65 TH/s') |
max | Optional | string | none | Maximum value label |
avg | Optional | string | none | Average value label |
className | Optional | string | none | Root class name from the host app |
MinMaxAvgValues type
type MinMaxAvgValues = Partial<{
min: string
max: string
avg: string
}>MinMaxAvgValues is the shape accepted by the minMaxAvg prop on both ChartContainer and ChartStatsFooter.
Basic usage
import { MinMaxAvg } from '@tetherto/mdk-react-devkit/core'
<MinMaxAvg min="65 TH/s" max="80 TH/s" avg="72.6 TH/s" />Usage with ChartContainer
import { ChartContainer, LineChart } from '@tetherto/mdk-react-devkit/core'
import { computeStats } from '@tetherto/mdk-react-devkit/core'
const stats = computeStats(values)
<ChartContainer
title="Hashrate"
minMaxAvg={{
min: `${stats.min} TH/s`,
max: `${stats.max} TH/s`,
avg: `${stats.avg} TH/s`,
}}
>
<LineChart data={chartData} />
</ChartContainer>Chart utilities
Pure functions for building Chart.js data and options. Import from the package root alongside components.
import {
defaultChartOptions,
defaultChartColors,
buildBarChartData,
buildBarChartOptions,
buildChartTooltip,
computeStats,
} from '@tetherto/mdk-react-devkit/core'| Export | Role |
|---|---|
defaultChartOptions | Shared Chart.js defaults used by MDK chart components |
defaultChartColors | Default dataset color palette |
buildBarChartData | Map MDK bar input into Chart.js data |
buildBarChartOptions | Build bar chart options (stacking, axes, formatters) |
buildChartTooltip | HTML tooltip config for Chart.js |
computeStats | Min, max, and average for a numeric array |
Types BarChartInput, BarChartSeries, BarChartLine, and BarChartConstant are exported from the same package for hook-shaped bar data.
Hook-shaped bar data
App and reporting hooks often return declarative bar input instead of Chart.js data. buildBarChartData converts that shape
into { labels, datasets } for BarChart. The pipeline:
- Input (
BarChartInput): optionallabels, requiredseries, optionallinesandconstantsfor mixed bar/line overlays. - Build (
buildBarChartData): returns Chart.jsdatawith MDK gradient styling and layout defaults (barWidth,categoryPercentage,barPercentageare optional on the input). - Data labels (optional): per-series overrides on the input (
formatter,anchor,align,offset,font,padding,display,clamp,clip) map to each built dataset’s Chart.jsdatalabelsby series index. - Render (
<BarChart data={...} />): pass the built object to the component; pair withbuildBarChartOptionswhen you need stacking, axes, or formatters.
BarChartInput shape
| Field | Type | Description |
|---|---|---|
labels | string[] | Optional category labels; omitted labels are derived from series values keys or indices |
series | BarChartSeries[] | Bar datasets (label, values, optional color, stack, gradient, bar layout props) |
lines | BarChartLine[] | Optional line overlays on the same chart |
constants | BarChartConstant[] | Optional horizontal reference lines |
Each BarChartSeries uses values as either number[] (positional) or Record<string, number> (keyed by category label).
Example
Hook output to BarChart example:
import {
BarChart,
buildBarChartData,
ChartContainer,
} from '@tetherto/mdk-react-devkit/core'
// Typical shape returned by app/reporting data hooks
const hookOutput = {
labels: ['Q1', 'Q2', 'Q3'],
series: [
{
label: 'Revenue',
values: [4.2, 3.8, 5.1],
color: '#72F59E',
dataLabels: {
formatter: (v: number) => `${v.toFixed(1)}M`,
anchor: 'end',
align: 'top',
},
},
{
label: 'OpEx',
values: [1.8, 2.0, 1.6],
color: '#FFD700',
},
],
}
const cleanSeries = hookOutput.series.map(({ dataLabels: _dl, ...s }) => s)
const base = buildBarChartData({ labels: hookOutput.labels, series: cleanSeries })
const chartData = {
labels: base.labels,
datasets: base.datasets.map((dataset, i) => {
const overrides = hookOutput.series[i]?.dataLabels
return overrides ? { ...dataset, datalabels: overrides } : dataset
}),
}
const isEmpty =
!hookOutput.series.length ||
hookOutput.series.every((s) => {
const vals = Array.isArray(s.values) ? s.values : Object.values(s.values)
return !vals.length || vals.every((v) => v === 0)
})
<ChartContainer title="Quarterly" empty={isEmpty}>
<BarChart data={chartData} />
</ChartContainer>Empty and all-zero series
Treat bar data as empty when any of the following is true:
seriesis missing or has length0- Every series has empty
values(array or record) - Every numeric value across all series is
0
Prefer ChartContainer empty or a placeholder instead of rendering a flat chart. After building Chart.js data, you can also
use useChartDataCheck from @tetherto/mdk-react-devkit/foundation
with { data: chartData }.