Shared axis, legend, tooltip, colors, and accessibility for the ChartLine, ChartBar, ChartScatter, ChartPie, and ChartFunnel roots.
Introduction
Bridge charts come as one root per chart family. Pick the root for the shape of your data; every root shares the same legend, tooltip, tokens, dark mode, and accessibility (summary, keyboard navigation, and a data table). The plot engine is ECharts.
| Root | Use for | Data |
|---|---|---|
| ChartLine | Trends, areas, stacked areas, steps, sparklines | ChartLineSeries, one value per category |
| ChartBar | Comparisons, rankings (horizontal), stacked totals, bar + line | ChartBarSeries (+ ChartLineSeries) |
| ChartScatter | Correlation between two numbers, bubbles | ChartScatterSeries, [x, y] points |
| ChartPie | Share of a whole (pie, donut) | data on the root |
| ChartFunnel | Conversion through ordered stages | data on the root |
This page covers the parts every root shares: ChartAxis, ChartLegend, ChartTooltip, colors, loading and empty states, and registry defaults.
| Part | Line | Bar | Scatter | Pie | Funnel |
|---|---|---|---|---|---|
| ChartLegend | ✅ | ✅ | ✅ | ✅ | ✅ |
| ChartTooltip | ✅ | ✅ | ✅ | ✅ | ✅ |
| ChartAxis | ✅ | ✅ | ✅ | — | — |
Compared to similar components:
- DataTable — Exact values the user reads, sorts, or filters. Prefer DataTable when the numbers matter more than the shape.
- Progress — A single value against a goal. Use a chart when there is more than one value to compare.
Use the framework selector in the site header to switch between React and Vue.
Install echarts v6 next to @bridge-ui/vue. Each root loads only its own ECharts series and the SVG renderer, and charts stay off the package root, so apps that never import a chart do not load ECharts.
Install echarts v6 next to @bridge-ui/react. Each root loads only its own ECharts series and the SVG renderer, and charts stay off the package root, so apps that never import a chart do not load ECharts.
Migrating from Chart and ChartSeries
Chart and ChartSeries were removed in v0.18.0. Move each chart to the root for its family:
| Before | After |
|---|---|
| Chart + ChartSeries (line) | ChartLine + ChartLineSeries |
| ChartSeries type="area" | ChartLineSeries area |
| Chart + ChartSeries type="bar" | ChartBar + ChartBarSeries |
| Bars and lines in one Chart | ChartBar + ChartBarSeries + ChartLineSeries |
| ChartAxis formatTick on category labels | ChartAxis formatCategory, which receives the category string |
| formatTick(value: number | string) | formatTick(value: number) (the value, or the timestamp on a time axis) |
| Registry Chart / ChartSeries | Registry ChartLine, ChartBar, ChartScatter, ChartPie, ChartFunnel (no entry per series) |
| Tooltip content context category | title |
<!-- before -->
<Chart :categories="months">
<ChartSeries type="bar" name="Orders" :data="orders" />
<ChartSeries type="area" name="Visitors" :data="visitors" />
<ChartAxis position="x" :format-tick="(value) => String(value).toUpperCase()" />
</Chart>
<!-- after -->
<ChartBar :categories="months">
<ChartBarSeries name="Orders" :data="orders" />
<ChartLineSeries area name="Visitors" :data="visitors" />
<ChartAxis position="x" :format-category="(month) => month.toUpperCase()" />
</ChartBar>// before
<Chart categories={months}>
<ChartSeries type="bar" name="Orders" data={orders} />
<ChartSeries type="area" name="Visitors" data={visitors} />
<ChartAxis position="x" formatTick={(value) => String(value).toUpperCase()} />
</Chart>
// after
<ChartBar categories={months}>
<ChartBarSeries name="Orders" data={orders} />
<ChartLineSeries area name="Visitors" data={visitors} />
<ChartAxis position="x" formatCategory={(month) => month.toUpperCase()} />
</ChartBar>Import
import { ChartAxis } from "@bridge-ui/vue/Components/ChartAxis";
import { ChartLegend } from "@bridge-ui/vue/Components/ChartLegend";
import { ChartTooltip } from "@bridge-ui/vue/Components/ChartTooltip";import { ChartAxis } from "@bridge-ui/react/Components/ChartAxis";
import { ChartLegend } from "@bridge-ui/react/Components/ChartLegend";
import { ChartTooltip } from "@bridge-ui/react/Components/ChartTooltip";Import the root and its series from their own pages: ChartLine, ChartBar, ChartScatter, ChartPie, and ChartFunnel.
Axes
position="x" is always the horizontal axis and position="y" the vertical one. On a horizontal ChartBar, the categories sit on y and the values on x. Pie and funnel charts have no axes.
formatCategory formats category labels. formatTick formats numbers: the value on a value axis, or the timestamp (ms) on a time axis. Grid lines are on for the value axis and off for the category axis by default.
Legend
Legend entries are toggle buttons: click to hide or show a series or slice, hover or focus to emphasize it. Set interactive to false for a static legend. position places it at the top, bottom, left, or right; left and right stack the entries beside the plot. align sets the entry alignment.
With slices (pie, funnel), showValue and showPercent add value and share columns. Format them with formatValue and formatPercent.
Tooltip
The tooltip title is the category (line, bar) or the series name (scatter). Slices (pie, funnel) show one row with the value and the share.
formatValue formats each value and formatPercent each share (default: the locale number format). slots.content replaces the title and rows (Vue: #content) and receives title, index, and the visible items.
Colors
Series and slices take palette colors in order, cycling when there are more items than colors. Override the palette on the root, or pass a token key or any CSS color to color on a series or slice.
Token keys (primary, info, success, warning, error, secondary, dark, black) follow light and dark mode automatically.
Colors can also follow the data:
- colorRanges on ChartLineSeries, ChartBarSeries, and ChartScatterSeries recolors points, bars, or stretches of a line by value (ChartLine, ChartBar, ChartScatter).
- categoryColors on ChartBar gives each category its own color, and tone="muted" lightens a series (ChartBar).
Color is never the only cue: range labels show in the tooltip, the data table, and the keyboard announcements.
Loading and empty
loading keeps the plot visible behind a translucent overlay with a spinner. A chart with no series or no values shows an empty message. Replace either with slots.loading and slots.empty (Vue: #loading and #empty).
Defaults and theme
Each root has its own registry entry: ChartLine, ChartBar, ChartScatter, ChartPie, and ChartFunnel. Series have no registry entry; set series options on the root instead (for example curve on ChartLine). ChartLegend takes align, interactive, and position. tokens.theme on a root sets the grid, axis, and label colors as Tailwind text-color classes. See Default props.
<BridgeUIProvider
:components="{
ChartLegend: { defaultProps: { position: 'top' } },
ChartBar: { defaultProps: { palette: ['primary', 'success'] } },
ChartLine: {
defaultProps: { curve: 'smooth', height: 320 },
tokens: { theme: { grid: 'text-dark-100 dark:text-dark-800' } },
},
}"
>
<App />
</BridgeUIProvider><BridgeUIProvider
components={{
ChartLegend: { defaultProps: { position: "top" } },
ChartBar: { defaultProps: { palette: ["primary", "success"] } },
ChartLine: {
defaultProps: { curve: "smooth", height: 320 },
tokens: { theme: { grid: "text-dark-100 dark:text-dark-800" } },
},
}}
>
<App />
</BridgeUIProvider>Keyboard
- Tab focuses the plot.
- ArrowLeft / ArrowRight (or ArrowUp / ArrowDown) move between items: categories, points, slices, or stages. Home / End jump to the first and last item. Escape clears the active item.
- The tooltip follows the keyboard, and the values are announced through a live region.
- Legend entries are buttons: Enter or Space toggles a series or slice.
Accessibility
- The root is a figure. The plot is a focusable img labelled by summary, or by a summary each root generates when it is omitted. Pass summary to describe the takeaway instead.
- A visually hidden data table with every value is always rendered.
- The tooltip is decorative (aria-hidden="true"); the same information is in the table and the announcements.
- Legend buttons expose their state with aria-pressed.
- The root gets aria-busy while loading is true.
- Engine animation is off under prefers-reduced-motion.
- The generated summaries and table headers are chrome strings; translate them through i18n.
Anatomy
<div> <!-- root, role="figure" -->
<div> <!-- plot, role="img", tabindex="0" -->
<div> <!-- ECharts host -->
<div> <!-- center (ChartPie donut) -->
<div> <!-- loading overlay -->
<div> <!-- empty overlay -->
<ul> <!-- ChartLegend root -->
<li>
<button> <!-- item: swatch + label (+ value, percent) -->
<div> <!-- ChartTooltip root, aria-hidden -->
<table> <!-- data table, sr-only -->
<div> <!-- live region, role="status" -->
</div>Target parts with classes and customProps. Every root: root, plot, center, loading, empty, and table. ChartLegend: root, item, swatch, label, value, and percent. ChartTooltip: root, title, item, swatch, label, value, percent, and note (the color range label).
Related components
ChartLine, ChartBar, ChartScatter, ChartPie, ChartFunnel, DataTable, Progress
API
Shared root props
Every root (ChartLine, ChartBar, ChartScatter, ChartPie, ChartFunnel) accepts these props. Family props are on each root’s page.
| Prop | Type | Default | Description |
|---|---|---|---|
| animation | boolean | true | Engine transitions. Always off under reduced motion. |
| children | ReactNode | — | Series, ChartAxis, ChartLegend, ChartTooltip. Use the default slot in Vue. |
| classes | ChartClasses | — | Classes for root, plot, center, loading, empty, and table. |
| customProps | ChartCustomProps | — | Extra props for root and plot. |
| height | number | string | 280 | Plot height. A number is in px. |
| loading | boolean | false | Shows the spinner overlay. |
| palette | ChartColorValue[] | primary, info, success, … | Colors in order, for series and slices without color. |
| size | ChartSize | "md" | Density of labels, legend, and tooltip. xs, sm, md, lg. |
| slots | ChartSlots | — | empty and loading. Vue: #empty and #loading. |
| summary | string | generated | Accessible description of the plot. |
| width | number | string | "100%" | Root width. A number is in px. |
ChartAxis
| Prop | Type | Default | Description |
|---|---|---|---|
| formatCategory | (category: string) => string | — | Category tick formatter. Vue: format-category. |
| formatTick | (value: number) => string | — | Value or time (ms) tick formatter. Vue: format-tick. |
| grid | boolean | true on the value axis, false on the category axis | Grid lines. |
| hidden | boolean | false | Hides the axis line and labels. |
| label | string | — | Axis title. |
| max | number | auto | Upper bound (value or time axis). |
| min | number | auto | Lower bound (value or time axis). |
| position | "x" | "y" | — | Required. Horizontal (x) or vertical (y) axis. |
| tickCount | number | auto | Preferred number of ticks. |
ChartLegend
| Prop | Type | Default | Description |
|---|---|---|---|
| align | "start" | "center" | "end" | "center" | Entry alignment. |
| classes | ChartLegendClasses | — | Classes for root, item, swatch, label, value, and percent. |
| customProps | ChartLegendCustomProps | — | Extra props for root and item. |
| formatPercent | (percent: number) => string | — | Share column formatter. Vue: format-percent. |
| formatValue | (value: number) => string | — | Value column formatter. Vue: format-value. |
| interactive | boolean | true | Entries toggle and emphasize their series or slice. |
| position | "top" | "bottom" | "left" | "right" | "bottom" | Where the legend sits. |
| showPercent | boolean | false | Share column (pie, funnel). Vue: show-percent. |
| showValue | boolean | false | Value column (pie, funnel). Vue: show-value. |
ChartTooltip
| Prop | Type | Default | Description |
|---|---|---|---|
| classes | ChartTooltipClasses | — | Classes for root, title, item, swatch, label, value, percent, and note. |
| customProps | ChartTooltipCustomProps | — | Extra props for root. |
| formatPercent | (percent: number, item: ChartTooltipItem) => string | — | Formats each share (pie, funnel). Vue: format-percent. |
| formatValue | (value: number, item: ChartTooltipItem) => string | locale number format | Formats each value. Vue: format-value. |
| slots | ChartTooltipSlots | — | content receives title, index, and items. Vue: #content. |