Corpora UI

Chart

Pie, area, line and bar charts for corpus research, with a passage or Strong’s reference pill, plot and legend. Series colours come from the --chart-series-1…5 tokens, grid from --chart-grid.

Preview

Use the controls to explore the component's props.

Props

PropTypeDefaultDescription
type (required)"pie" | "area" | "line" | "bar"—Plot kind.
data (required){ label: string; [key]: number | string | null }[]—One row per x label (or pie slice).
series (required){ key, label, color?, format? }[]—Keys to plot; colour defaults to the series token by position. Pie uses the first. format renders the value in the legend and hover tooltip.
title / subtitle / badgeReactNode—Header row; badge defaults to the type name.
referenceReference props (children, href?, preview?, onClick?)—Passage or Strong’s entry displayed as a reference pill instead of the type badge.
center{ value, label? }—Pie only: donut centre.
headerless / plotHeightboolean / number—Bare plot for embedding (InsightCards).

Example

The four plots show commentary entries per author for John 3:16 (pie), cumulative cross-reference links through John 3:14–18 (area), cross-reference counts per verse and testament (line), and tokens matching Strong’s G26 in selected Bible books (bar). Counts are illustrative fixtures; connect data to your own indexed corpus for research results.

Commentaries by authorEntries on the selected verse
36entries
Cross-reference coverageCumulative links through the passage
Cross-referencesLinked passages by testament
Word occurrencesMatched tokens by Bible book

Illustrative corpus counts for these examples; not statistics from a published Bible edition or commentary collection.

import { Chart } from "@exegia/corpora-ui"

;<Chart
  type="bar"
  title="Word occurrences by book"
  subtitle="Illustrative counts · selected Bible books"
  reference={{
    children: "Strong’s G26",
    preview: "Tokens matching the selected Strong’s entry, grouped by book.",
  }}
  data={[
    { label: "Romans", occurrences: 14 },
    { label: "1 Cor.", occurrences: 13 },
    { label: "Eph.", occurrences: 9 },
    { label: "1 John", occurrences: 18 },
  ]}
  series={[{ key: "occurrences", label: "Occurrences" }]}
/>

ECharts configuration

The renderer uses vendored EvilCharts ECharts components, with echarts as a runtime dependency. Existing imports and the four plot types remain supported. The default pie remains a donut; use pie={{ innerRadius: 0 }} for a solid pie.

PropDefaultBehavior
variant"default"stacked and percent apply to area/bar; horizontal applies to bar; donut applies to pie. Other combinations use the default plot.
renderer / animation"canvas" / trueCanvas or SVG rendering; animation also respects reduced motion.
loading / emptyContentfalse / "No data"Loading skeleton or an empty-state message; loading hides the legend.
showLegend / interactivetrue / falseShow the accessible HTML legend; enable keyboard and pointer selection.
grid / xAxis / yAxistrue / true / falseCartesian grid and axes. Axis objects accept label, tickFormatter, and hideDots.
tooltiptrueBoolean or { variant, roundness, cursor, position }; defaults to frosted-glass; default provides a solid background. Tooltips preserve React labels and series formatters.
brushfalseCartesian zoom brush; accepts height, formatLabel, and onChange({ startIndex, endIndex }). Horizontal bars omit the brush.
curveType"monotone"Line/area interpolation, including linear, smooth, and step.
pie—Radius, angles, corner radius, padding and clickability settings.
chartOptions—Advanced ECharts options, shallowly overriding generated options.

Series accept area, line, and bar configuration objects. Area fills include gradient, solid, dotted, lines, hatched, and none. Bar styles include default, gradient, hatched, duotone, stripped, blocks, and expandable. Line settings include strokeVariant, strokeWidth, glowing, and connectNulls.

<Chart
  type="area"
  variant="stacked"
  data={data}
  series={[
    { key: "oldTestament", label: "Old Testament", area: { variant: "gradient" } },
    { key: "newTestament", label: "New Testament", area: { variant: "hatched" } },
  ]}
  interactive
  brush
  plotHeight={260}
/>

State and methods

Give each chart a unique chartId to address it from another component under the same Jotai provider. Omit the ID for an isolated chart. selectedKey controls selection; defaultSelectedKey seeds uncontrolled selection. For pie charts, keys are row labels; for other charts, keys are series keys. Keys must be unique. onSelectionChange reports changes, and invalid keys are ignored.

import { Chart, useChartActions, useChartState } from "@exegia/corpora-ui"

function SelectionControls() {
  const { selectedKey } = useChartState("research")
  const chart = useChartActions("research")
  return <button onClick={chart.clearSelection}>Clear {selectedKey ?? "selection"}</button>
}

// Mount both under the same Jotai Provider.
<Chart chartId="research" type="bar" data={data} series={series} interactive />

Actions expose select(key), toggle(key), clearSelection(), and reset() (restores the default selection). The same methods are exposed through a React ref. In controlled mode, actions request changes through onSelectionChange; the parent must update selectedKey.

For narrow subscriptions, use chartSelectedKeyAtom(chartId). chartStateAtom, selectChartKeyAtom, toggleChartKeyAtom, and resetChartAtom are also exported. Call removeChartInstance(id) after all consumers of a named chart unmount to release its cached atoms. Generated IDs are cleaned up automatically. Children can obtain the enclosing ID through useChartContext().

Implementation modules follow the scaffold structure: chart-root, chart-plot, chart-legend, chart-tooltip, chart-atom, chart-context, use-chart, use-chart-state, type, constants, and utils. The original chat/chart entry point remains compatible.

Consumer sizing and outer component

width and height size the whole chart component, including its header and legend. Numbers mean pixels; CSS lengths such as "100%", "28rem", and "clamp(18rem, 50vh, 32rem)" also work. Percentage heights require a parent with a defined height. Without sizing props, the compact defaults remain unchanged.

When height (or style.height) is set, the plot fills the remaining space. plotHeight overrides that automatic fill and accepts CSS lengths too. style takes precedence over width and height; className remains available for responsive widths. A fixed outer height must leave enough room for the header, legend, and any children.

Use the coss/Base UI render prop to replace the outer element or supply your own component. It works with both the framed and headerless layouts. Custom components must forward their props, children, and DOM ref. The chart's own ref continues to expose selection actions.

<Chart
  type="bar"
  data={data}
  series={series}
  width="100%"
  height={360}
  render={<section aria-label="Word occurrences" />}
/>

<Chart
  type="pie"
  data={data}
  series={series}
  headerless
  width="100%"
  plotHeight="12rem"
  render={<MyChartSurface />}
/>

Last updated on

On this page