MDK Logo

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

ComponentDescription
ChartContainerWrapper for charts with title and loading states
MinMaxAvgMin / max / avg summary row

ChartContainer

Wrapper for charts with loading and empty states.

Import

import { ChartContainer } from '@tetherto/mdk-react-devkit/core'

Props

PropStatusTypeDefaultDescription
childrenRequiredReactNodenoneChart body (for example a BarChart or LineChart)
titleOptionalstringnoneTitle text
headerOptionalReactNodenoneCustom header node
legendDataOptionalLegendItem[]noneLegend entries rendered in the container chrome
highlightedValueOptionalobjectnoneHighlighted 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)
rangeSelectorOptionalobjectnoneRange selector props (options, value, onChange, optional className, style, buttonClassName)
loadingOptionalbooleannoneWhen true, shows a centered Loader overlay over the chart area
emptyOptionalbooleannoneWhen true, shows empty state
emptyMessageOptionalstring'No data available'Copy shown in the empty overlay when empty is true and loading is not true
minMaxAvgOptionalobjectnoneMin / max / avg strings for the summary row
timeRangeOptionalstringnoneTime range label
footerOptionalReactNodenoneFooter slot
footerClassNameOptionalstringnoneClass name on the footer wrapper
onToggleDatasetOptionalfunctionnoneCalled with dataset index when legend toggles visibility
classNameOptionalstringnoneRoot 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

PropStatusTypeDefaultDescription
minMaxAvgOptionalobjectnoneMin, max, and average strings shown in the primary row when provided
statsOptionalChartStatsFooterItem[]noneAdditional stat rows (label, value) in a columnar grid
statsPerColumnOptionalnumber1Number of stat items per column when stats is set
secondaryLabelOptionalobjectnoneSecondary block with title and value when provided
classNameOptionalstringnoneRoot 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

PropStatusTypeDefaultDescription
itemsRequiredDetailLegendItem[]noneLegend rows (label, color, optional icon, currentValue, percentChange, hidden)
onToggleOptionalfunctionnoneCalled with label and index when a row is toggled
classNameOptionalstringnoneRoot 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

PropStatusTypeDefaultDescription
minOptionalstringnoneMinimum value label (for example '65 TH/s')
maxOptionalstringnoneMaximum value label
avgOptionalstringnoneAverage value label
classNameOptionalstringnoneRoot 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'
ExportRole
defaultChartOptionsShared Chart.js defaults used by MDK chart components
defaultChartColorsDefault dataset color palette
buildBarChartDataMap MDK bar input into Chart.js data
buildBarChartOptionsBuild bar chart options (stacking, axes, formatters)
buildChartTooltipHTML tooltip config for Chart.js
computeStatsMin, 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:

  1. Input (BarChartInput): optional labels, required series, optional lines and constants for mixed bar/line overlays.
  2. Build (buildBarChartData): returns Chart.js data with MDK gradient styling and layout defaults (barWidth, categoryPercentage, barPercentage are optional on the input).
  3. 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.js datalabels by series index.
  4. Render (<BarChart data={...} />): pass the built object to the component; pair with buildBarChartOptions when you need stacking, axes, or formatters.

BarChartInput shape

FieldStatusTypeDescription
seriesRequiredBarChartSeries[]Bar datasets (label, values, optional color, stack, gradient, bar layout props)
labelsOptionalstring[]Category labels; omitted labels are derived from series values keys or indices
linesOptionalBarChartLine[]Line overlays on the same chart
constantsOptionalBarChartConstant[]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:

  • series is missing or has length 0
  • 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 }.

On this page