Skip to content

Components · Charts

ChartFrame

The container every chart sits in: title, controls, legend, loading / empty / error states and an accessible data table.

@rookcom/monarch-react/chartsComponent

Header controls, legend and table toggle

Requests

New requests per day

  • Requests
Requests
DayRequests
Mon48
Tue61
Wed55
Thu72
Fri66

Usage examples

Loading, empty and error

Purpose

Gives every chart the same frame and the same accessibility: a labelled figure, a header with period or metric controls, a legend, consistent loading, empty and error states, and the data as a real table, visible on demand and always present for screen readers.

Use when

  • Wrapping a custom visualisation that Monarch does not ship, so it still gets the header, states and table fallback.
  • Building a new chart component: LineChart and BarChart render ChartFrame for you, and the other ./charts components build on it.

Avoid when

  • A single headline number with no plot: use StatCard.
  • A plain list of labelled values: use DescriptionList or BarList.

Design principles

  • The data is never only a picture: table is always rendered for assistive technology and one click away for everyone else.
  • States keep the reserved height, so loading, empty, error and ready swap without the page jumping.
  • Controls belong in the header (actions), above the plot, in one row that wraps on narrow screens.
  • A legend only for two or more series; a single series is named by the title.
  • Series colours are palette slots (chartColor(1…5) → --mn-color-data-*), never status colours and never raw values.

API reference

import { ChartFrame, chartColor } from '@rookcom/monarch-react/charts';
ExportKindRenderingRoot class
ChartFramecomponentclient.mn-chart-frame
chartColorutilityserver-safe–

ChartFrame renders a <figure> (ref to it) labelled by title and described by description; other HTML attributes pass through.

chartColor(slot) returns the CSS colour for a palette slot (1–5 → var(--mn-color-data-N), neutral → var(--mn-color-text-subtle)), for custom marks drawn inside a frame.

Types shared by every chart are exported from here: ChartSeries, ChartDatum, ChartColor, ChartLegendItem, ChartTableData, ChartTableColumn.

Generated from the TypeScript declarations of packages/react/src/components/charts/chart-frame.

Properties

ChartFrame

The container every Monarch chart sits in: a `<figure>` with a title, description, controls slot, legend, loading / empty / error states and an accessible data table ("View as table", always present for screen readers).

PropTypeDescription
title requiredReactNodeThe chart's name. Labels the figure. Required.
actionsReactNodePeriod or metric controls in the header, such as a pill TabsFilter or a Select.
childrenReactNodeThe chart.
classNamestring
defaultShowTablebooleanUncontrolled initial table view. Default `false`.
descriptionReactNodeOne line under the title: the period, unit or what the chart answers. Describes the figure.
emptyActionsReactNodeActions in the empty state, such as a link to set up tracking.
emptyDescriptionReactNodeEmpty-state description, such as what will appear and when.
footerReactNodeNotes under the chart: source, last updated, a footnote.
headingLevelChartFrameHeadingLevelRender the title as a heading (`h2`–`h6`) to match the page outline. Default: not a heading.
heightnumberHeight reserved for the chart body (loading, empty and error keep it, so nothing jumps). Default 240.
idstring
labelsChartFrameLabels
legendreadonly ChartLegendItem[]Legend entries, shown under the header while the chart is visible.
legendMarkerChartLegendMarkerLegend marker shape. Default `line`.
onLegendToggle((key: string) => void)Makes legend entries toggle buttons; called with the series key.
onRetry(() => unknown)Error-state retry. Return the refetch promise to keep the button busy until it settles.
onShowTableChange((showTable: boolean) => void)
showTablebooleanControlled table view.
statusChartFrameStatus`ready` (default) shows the chart; `loading` a skeleton with `aria-busy`; `empty` an empty state; `error` an error with Try again when `onRetry` is set. Exposed as `data-status`.
tableChartTableDataThe accessible data table: every value the chart shows, as text. It is always in the page for screen readers, and visible through the "View as table" toggle when `tableToggle` is on.
tableTogglebooleanShow the "View as table" toggle. Default `true` when `table` is set.

Variants

PropValuesDescription
status'ready''loading''empty''error'Which body shows: the chart, a skeleton, an EmptyState or an error (InlineErrorRetry with onRetry, otherwise an alert). Exposed as data-status.
headingLevel'2''3''4''5''6'Renders the title as that heading; without it the title is a plain block.
legendMarker'line''square'Short line (line charts) or square (bars) beside each legend label.
tableToggle'true''false'Shows the "View as table" button (default when table is set). Off, the table is still present for screen readers.

States

StateExposed asBehaviour
Readydata-status="ready", data-view="chart"The chart, plus the visually hidden table.
Table viewdata-view="table"The table replaces the chart in a focusable, scrollable region; the legend hides.
Loadingdata-status="loading", aria-busy="true"A skeleton of the reserved height and a polite "Loading chart" status.
Emptydata-status="empty"A compact EmptyState with emptyDescription and emptyActions.
Errordata-status="error"InlineErrorRetry with Try again when onRetry is set; otherwise a message with role="alert".
Hidden seriesaria-pressed="false", data-hiddenA toggled-off legend entry: struck-through label and faded swatch.

Interaction behaviour

  • "View as table" swaps the chart for the table and changes to "View as chart"; controlled with showTable + onShowTableChange, or uncontrolled with defaultShowTable.
  • With onLegendToggle, each legend entry is a toggle button; the chart decides what hiding means.
  • Try again calls onRetry; return the refetch promise and the button stays busy until it settles.

Keyboard support

KeysAction
TabMoves through the header controls, the table toggle, legend toggles and the chart.
Enter / SpaceActivates the table toggle or a legend toggle.
Arrow keys (table view)Scroll the focused table region when it overflows.

Accessibility

Role
figure
Accessible name
title (aria-labelledby); description is the accessible description.
  • The data table has a caption (the title unless table.caption is set), column headers with scope="col" and row headers with scope="row".
  • While the chart shows, the table sits in a visually hidden container, so screen readers always reach the values.
  • The visible table is a focusable region (tabindex="0"), so keyboard users can scroll it.
  • Legend toggles are buttons with aria-pressed; the legend list is named "Legend" (labels.legend).
  • Loading sets aria-busy and announces "Loading chart"; a retry-less error is role="alert".
  • Identity is never colour alone: every legend entry has its label, dashed series show a dashed marker.
  • All text is translatable through labels.

Responsive behaviour

  • The header wraps: actions move under the title when there is no room.
  • Padding tightens below 30rem; the frame works at 320px.
  • Legend toggles grow to a 44px touch target on coarse pointers.

Theme support

  • Surface, border and text use Monarch tokens and follow light, dark and high-contrast themes.
  • Series colours are --mn-color-data-1 … -5, chosen and contrast-checked per theme in @rookcom/monarch-tokens (3:1 on every chart background, 4.5:1 in high contrast).
  • Focus rings use --mn-color-focus-ring.

Do and don't

Do

  • Pass table with every value the chart shows, formatted as the chart formats it.
  • Reserve a height close to the real chart so states do not shift the layout.
  • Put period and metric switches in actions.

Don't

  • Hide the only text alternative: never set tableToggle={false} and leave out table.
  • Colour series with status tokens or hex values; use chartColor slots.
  • Put a legend on a single-series chart.
  • LineChart: Trends over time; renders ChartFrame for you.
  • BarChart: Comparisons across categories; renders ChartFrame for you.
  • Sparkline: A word-sized trend with no frame, for tables and cards.
  • StatCard: One headline number, optionally with a sparkline.
  • Card: A general container when there is no chart.

Dependencies

KindDepends on
npm packagesreact
Monarch componentsButton, EmptyState, InlineErrorRetry, Skeleton

Shared chart internals (legend, table, palette) come from src/internal/charts; their styles are styles/chart.css (.mn-chart__*).

Testing coverage

  • Figure named by the title and described by the description; no axe violations.
  • The data table is always present (visually hidden) with row and column headers.
  • The toggle swaps chart and table, uncontrolled and controlled; the visible table is a focusable region.
  • tableToggle={false} removes the button but keeps the hidden table.
  • Heading level and actions slot render.
  • Loading (aria-busy, status text), empty (description, actions) and error (Try again calls onRetry; alert without it; translated labels).
  • Legend toggles expose aria-pressed and report the key; a static legend has no buttons.
  • chartColor maps slots to data tokens only.
  • Renders on the server.
CheckCovered
Axe in jsdomYes
Server renderingYes
Browser suitesVisual baselines: /__gallery/chart-frame; Cross-browser axe: /components/chart-frame

Tests: packages/react/src/components/charts/chart-frame