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
ChartStatsFooterStatistics row displayed below charts
DetailLegendChart legend with detailed value display

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

Displays statistics below charts.

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

Detailed chart legend with values.

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: '%' } },
  ]}
/>

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

FieldTypeDescription
labelsstring[]Optional category labels; omitted labels are derived from series values keys or indices
seriesBarChartSeries[]Bar datasets (label, values, optional color, stack, gradient, bar layout props)
linesBarChartLine[]Optional line overlays on the same chart
constantsBarChartConstant[]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:

  • 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