Bullet chart
One measure against a target and qualitative bands, a row per KPI, as Stephen Few drew it for scorecards.
c2-bullet-chart
A bullet chart: one measure against a target and qualitative bands, as Stephen Few drew it for KPI scorecards. Each
row of data is one bullet, on its own scale; several stack, horizontal by default. Drawn by ECharts.
label-field names a row and description-field adds a muted second line, for the unit. The one c2-chart-series
is the measure, drawn as a bar a third of the band height. target-field (or target for every row) is the target,
a tick across the bar, and bands-field (or bands) the band boundaries, ascending: [150, 225, 300] draws three
bands, 0–150, 150–225 and 225–300, from poor to good. A row's scale runs from min to the largest of its last band,
its value and its target, unless max-field or max sets the end; scale="shared" puts every row on one scale.
With better="lower" the band colours run the other way, so the good band sits near zero.
<c2-bullet-chart label-field="kpi" description-field="unit" target-field="target" bands-field="bands"
data='[{ "kpi": "Revenue", "unit": "US$, thousands", "actual": 270, "target": 250, "bands": [150, 225, 300] }]'>
<c2-chart-series field="actual" label="Actual"></c2-chart-series>
</c2-bullet-chart>
The bands are a grey ramp from --c2-chart__band-start--color (poor) to --c2-chart__band-end--color (good), and
--c2-chart__band-1--color … --c2-chart__band-5--color replace one position, poorest first, for status tints.
The chart sizes itself: unless --c2-chart--height is set, it is as tall as its rows, --c2-chart__row--height
each. orientation="vertical" turns the rows into columns.
Hovering a row shows the value, the target with the share reached, and the band the value falls in. The plot is one
tab stop: the arrow keys move between rows, Home and End go to the first and last, Enter highlights a row and
Escape clears it, and a live region reads the focused row. Clicking a row fires point-click and highlights it.
Attributes
| Name | Type | Default | Description |
|---|---|---|---|
description-field | string | — | Row field holding a muted second line under the name, for the unit; may be a dotted path. |
target-field | string | — | Row field holding each row's target; may be a dotted path. |
target | number | undefined | — | The target of every row without a target-field. |
bands-field | string | — | Row field holding each row's band boundaries, ascending, as an array; may be a dotted path. |
bands | number[] | undefined | — | The band boundaries of every row without a bands-field, ascending, as a JSON array: [150, 225, 300]. Two to five bands. |
band-labels | string | — | The names of the bands, poorest first, as a comma list or a JSON array (for names holding a comma), for the tooltip, the table and the announcement. The default follows the band count: "Poor, Satisfactory, Good" for three. |
min | number | 0 | Where every scale starts. |
max | number | undefined | — | Where every scale ends, when there is no max-field. Unset, each row ends at the largest of its last band, value and target. |
max-field | string | — | Row field holding each row's scale end; may be a dotted path. |
scale | 'row' | 'shared' | row | row (the default) gives each row its own scale; shared puts every row on one, for measures in the same unit. |
better | BulletBetter | higher | Which end of the scale is good: higher (the default), or lower, which turns the band colours round so the good band sits near zero. |
color-field | string | — | Row field holding each row's bar colour. |
orientation | 'horizontal' | 'vertical' | horizontal | horizontal (the default) stacks the rows; vertical sets them side by side as columns. |
labels | 'start' | 'none' | start | Whether each row's name and description are drawn: start (the default) before the bands, or none. |
value-labels | 'end' | 'none' | end | Whether each row's value is printed: end (the default) after the bands, or none. |
axis | 'row' | 'none' | row | Whether each row draws its own tick axis: row (the default), or none. |
value-suffix | string | — | Text appended to the values, targets and band ranges, such as %. |
precision | number | undefined | — | Maximum number of decimal places in the values. Unset, up to two. |
renderer | 'canvas' | 'svg' | canvas | Which ECharts renderer to use. SVG prints and scales crisply; canvas is faster with many marks. |
aria-label | CustomEvent | — | The chart's accessible name, read by a screen reader on the plot before its data table. Without it the chart describes itself from its type, series and size. |
data | ChartInput | undefined | — | The data to plot. Row objects, a bare number[], columnar [xs, ys…], or an already-normalised
frame. Compared by identity: replace the array, or bump revision after mutating it in place. |
revision | number | 0 | Bump after mutating data in place. The cheap escape hatch for a large buffer you own. |
series | ChartSeriesConfig[] | undefined | — | Series definitions, as an alternative to c2-chart-series children. Children win when both are set. |
x-field | string | — | Row field holding the x value; may be a dotted path. Defaults to the row index. |
label-field | string | — | Row field holding each row's label: the slice names of a pie, the category axis of a bar chart, and the x tick
labels of a line, area or sparkline chart (label-field="month", or "year" to print 2021 rather than 2,021). |
x-type | 'time' | 'linear' | 'category' | linear | How x values are interpreted, which decides the axis and the tooltip format. |
legend | 'none' | 'top' | 'bottom' | 'start' | 'end' | bottom | Where the legend sits, or none to hide it. Shown by default: a chart with more than one series is
unreadable without one, and a single-series chart simply renders a one-entry legend. |
legend-action | 'toggle' | 'highlight' | highlight | What clicking a legend entry does. highlight (the default) emphasises the series and dims the others, and a
second click clears the highlight, just as a click on the series in the plot does; toggle hides or shows the
series instead. A linked c2-chart-legend follows the same mode. |
highlighted | string | null | null | Key of the series drawn emphasised, the others dimmed: the series field, or a pie's slice label, or an overlap
chart's set key. Set by a legend click in highlight mode, and settable from the application in either mode. |
tooltip | 'none' | 'item' | 'axis' | axis | Whether the tooltip follows the whole x position or only the hovered datum. |
animation | 'none' | 'auto' | auto | Whether the chart animates its initial draw. ECharts uses its native shape animation and uPlot uses a
lightweight plot reveal; subsequent data updates stay immediate so a live source does not animate
every tick. Named animation rather than animate because HTMLElement.animate() is a method every
element already has, and shadowing it breaks the Web Animations API on the host. |
locale | string | undefined | — | BCP 47 locale for the axis and tooltip formatting. Defaults to the browser locale. |
loading | boolean | false | Shows the loading state instead of the plot. |
error | string | — | Shows an error message instead of the plot. |
empty-message | string | No data | Replaces the built-in "no data" text. |
max-points | number | 0 | Caps how many points a streaming chart keeps; older points fall off the front. 0 keeps everything. |
lazy-render | boolean | false | Defers loading the engine until the host first scrolls into view. |
annotations | ChartAnnotation[] | undefined | — | Markers at an x value and shaded x ranges, drawn over the plot of a cartesian chart (line, area, bar, sparkline,
scatter, bubble, candlestick) and placed by the engine's own x scale, so they follow the axes, a resize and a
zoom. x/x2 are x values: what x-field holds (epoch milliseconds on a time chart), else the row index. Each
marker is a button, reachable with Tab and named by its label and x, that fires annotation-click. The
other charts (pie, gauge, radar, pyramid, butterfly, heatmap, overlap, chord, map) ignore it. |
Slots
| Name | Description |
|---|---|
default | The series definitions: c2-chart-series elements. They render nothing themselves. |
legend | Replaces the built-in legend. The built-in one is still what legend positions. |
tooltip | Replaces the built-in tooltip body. The hovered point is available through the renderTooltip property when a function is easier than markup. |
actions | Controls pinned to the top-right of the plot area, for a range picker or an export button. |
empty | Replaces the built-in "no data" message. |
loading | Replaces the built-in message shown while loading is set. |
error | Replaces the built-in message shown when error is set. |
Events
| Name | Type | Description |
|---|---|---|
tooltip-change | CustomEvent<ChartTooltipContext | null> | Fired with the complete tooltip model as the pointer moves, and with null when it leaves. Used by c2-chart-tooltip. |
series-toggle | CustomEvent<ChartSeriesToggleEventDetail> | Fired when a series is hidden or shown, from the legend with legend-action="toggle" or through setSeriesVisible. Does not bubble. |
series-highlight | CustomEvent<ChartSeriesHighlightEventDetail> | Fired when the reader highlights a series, from the legend or by clicking it in the plot, or clears the highlight. detail.key names it, or is null. Does not bubble. |
legend-change | CustomEvent<ChartLegendChangeEventDetail> | Fired when legend entries or visibility change. Used by c2-chart-legend. |
chart-ready | CustomEvent<{ engine: string }> | Fired after the engine has loaded and drawn for the first time. The host also matches :state(ready) from then on, which is what a test should wait on. |
chart-error | CustomEvent<{ error: unknown }> | Fired when the engine fails to load or to draw. detail.error is the underlying failure. |
range-change | CustomEvent<ChartRangeEventDetail> | Fired after the user zooms or brushes. detail.min and detail.max are the new x bounds. Does not bubble. |
point-hover | CustomEvent<ChartPointEventDetail | null> | Fired as the pointer moves between data points, and with a null detail when it leaves the plot. Does not bubble. |
annotation-click | CustomEvent<ChartAnnotationEventDetail> | Fired when an annotation's marker is clicked, or activated from the keyboard. detail.annotation is the entry and detail.index its position in annotations. Does not bubble. |
point-click | CustomEvent<ChartPointEventDetail> | Fired when a datum is clicked; the chart then highlights the clicked series (a second click on it clears the highlight). Cancelable: preventDefault() keeps the highlight as it is. Does not bubble: several components fire point events, so a listener belongs on the element itself. |
CSS parts
Shadow DOM styling hooks used with ::part(name). Prefer CSS custom properties when they cover the change.
| Name | Description |
|---|---|
frame | The outer flex column holding the legend and the plot area. |
plot-area | The positioned box the engine draws into. |
plot | The engine's container element. Carries no Lit bindings, so the canvas survives every update. |
overlay | The non-interactive layer above the canvas that holds the tooltip and the actions. |
tooltip | Component-owned bubble containing the tooltip slot and its generated fallback content. |
actions | The container for the actions slot. |
annotations | The layer holding the annotations, above the plot and below the tooltip. |
annotation | One annotation: the box from x to x2, or a zero-width box at x. |
annotation-range | The shaded fill of a range annotation. |
annotation-line | The rule drawn at an annotation's x. |
annotation-marker | The focusable button at the top of an annotation's rule. |
state | Shared message layer containing the empty, loading, or error slot and its fallback state. |
legend | Component-owned container wrapping the legend slot and generated legend fallback. |
legend-item | One legend entry, a toggle button. |
legend-marker | The colour swatch inside a legend entry. |
CSS custom properties
Grouped by semantic target and state from --c2-<component>__<target>__<state>--<property>. Click a group to collapse it; click a name to copy it.
| Name | Type | Default | Description |
|---|---|---|---|
--c2-chart--width | length | 100% | Width of the host. The plot is absolutely positioned and has no intrinsic width, so a chart used as a flex item would otherwise collapse to its legend. |
--c2-chart--height | pixel | 320px | Height of the host. A canvas has no intrinsic size, so this is what gives the chart a box. |
--c2-chart--background | color | #ffffff | Background of the chart surface. |
--c2-chart--color | color | #18181b | Primary text colour. |
--c2-chart--font-family | font-family | inherit | Font family used for the chart chrome and the labels the engine draws. |
--c2-chart--font-size | font-size | 12px | Base font size. |
--c2-chart--padding | padding | 12px | Padding around the whole chart. |
--c2-chart--border-top | border | 1px solid #e4e4e7 | Top border. |
--c2-chart--border-right | border | 1px solid #e4e4e7 | Right border. |
--c2-chart--border-bottom | border | 1px solid #e4e4e7 | Bottom border. |
--c2-chart--border-left | border | 1px solid #e4e4e7 | Left border. |
--c2-chart--border-top-left-radius | border-radius | 8px | Top-left corner radius. |
--c2-chart--border-top-right-radius | border-radius | 8px | Top-right corner radius. |
--c2-chart--border-bottom-left-radius | border-radius | 8px | Bottom-left corner radius. |
--c2-chart--border-bottom-right-radius | border-radius | 8px | Bottom-right corner radius. |
--c2-chart__band-start--color | color | #d4d4d8 | The poorest band; the bands between mix evenly towards --c2-chart__band-end--color. |
--c2-chart__band-end--color | color | #f4f4f5 | The best band. |
--c2-chart__band-1--color | color | — | Replaces the colour of the poorest band, for status tints. Unset, the band follows the ramp. |
--c2-chart__band-2--color | color | — | Replaces the colour of the second band from the poorest. Unset, it follows the ramp. |
--c2-chart__band-3--color | color | — | Replaces the colour of the third band from the poorest. Unset, it follows the ramp. |
--c2-chart__band-4--color | color | — | Replaces the colour of the fourth band from the poorest. Unset, it follows the ramp. |
--c2-chart__band-5--color | color | — | Replaces the colour of the fifth band from the poorest. Unset, it follows the ramp. |
--c2-chart__target--color | color | #18181b | The target tick. Falls back to --c2-chart--color. |
--c2-chart__target--width | pixel | 3px | Width of the target tick. |
--c2-chart__bar--border-radius | number | 0 | Roundedness of the measure bar's corners, from 0 (square) to 0.5 (fully rounded). |
--c2-chart__row--height | pixel | 44px | Height of a row, its tick axis included (24px with axis="none"). The chart is as tall as its rows unless --c2-chart--height is set; then the rows share that height. |
--c2-chart__row--gap | pixel | 12px | Space between two rows (two columns when vertical). |
--c2-chart__label--font-weight | font-weight | 600 | Weight of a row's name and value. |
--c2-chart__description--color | color | #71717a | Colour of a row's description. Falls back to --c2-chart__muted--color. |
--c2-chart__series__dimmed--opacity | opacity | 0.25 | Opacity the other rows keep while one is highlighted. |
--c2-chart__plot__focus--outline | border | 2px solid rgba(2, 101, 220, 0.4) | Focus ring of the plot, the chart's tab stop. |
--c2-chart__series-1--color | color | #0265dc | Colour of the first series. |
--c2-chart__series-2--color | color | #ea580c | Colour of the second series. |
--c2-chart__series-3--color | color | #0f766e | Colour of the third series. |
--c2-chart__series-4--color | color | #db2777 | Colour of the fourth series. |
--c2-chart__series-5--color | color | #a16207 | Colour of the fifth series. |
--c2-chart__series-6--color | color | #7c3aed | Colour of the sixth series. |
--c2-chart__series-7--color | color | #0891b2 | Colour of the seventh series. |
--c2-chart__series-8--color | color | #52525b | Colour of the eighth series. Series beyond the eighth reuse the palette from the start. |
--c2-chart__axis--color | color | #71717a | Colour of the axis lines and tick labels. |
--c2-chart__axis--font-size | font-size | 12px | Font size of the tick labels. |
--c2-chart__grid--color | color | #e4e4e7 | Colour of the grid lines. |
--c2-chart__crosshair--color | color | #a1a1aa | Colour of the cursor crosshair. |
--c2-chart__crosshair--width | pixel | 1px | Width of the cursor crosshair. |
--c2-chart__surface--color | color | #ffffff | Surface colour handed to the engine, for marker borders and label backdrops. |
--c2-chart__muted--color | color | #71717a | Secondary text colour. |
--c2-chart__positive--color | color | #16a34a | Colour for a rising value, used by the candlestick chart and as the sparkline's positive tone. |
--c2-chart__negative--color | color | #dc2626 | Colour for a falling value, used by the candlestick chart and as the sparkline's negative tone. |
--c2-chart__legend--gap | pixel | 12px | Gap between legend entries. |
--c2-chart__legend--padding | padding | 8px 0 0 | Padding around the legend. |
--c2-chart__legend--color | color | #71717a | Legend text colour. |
--c2-chart__legend--font-size | font-size | 12px | Legend font size. |
--c2-chart__legend__disabled--opacity | opacity | 0.38 | Opacity of the legend entries that are not highlighted while one is, or, with legend-action="toggle", of an entry whose series is hidden. |
--c2-chart__legend-marker--size | pixel | 10px | Size of the legend colour swatch. |
--c2-chart__legend-marker--border-radius | border-radius | 999px | Corner radius of the legend colour swatch. |
--c2-chart__tooltip--background-color | color | #18181b | Tooltip background. |
--c2-chart__tooltip--color | color | #fafafa | Tooltip text colour. |
--c2-chart__tooltip--font-size | font-size | 12px | Tooltip font size. |
--c2-chart__tooltip--padding | padding | 8px 10px | Tooltip padding. |
--c2-chart__tooltip--border-radius | border-radius | 6px | Tooltip corner radius. |
--c2-chart__tooltip--box-shadow | box-shadow | 0 8px 24px rgba(24, 24, 27, 0.08) | Tooltip shadow. |
--c2-chart__tooltip--gap | pixel | 6px | Gap between tooltip rows. |
--c2-chart__annotation--color | color | #71717a | Colour of a neutral annotation (the default tone). |
--c2-chart__annotation__info--color | color | #0265dc | Colour of an info annotation. |
--c2-chart__annotation__success--color | color | #16a34a | Colour of a success annotation. |
--c2-chart__annotation__warning--color | color | #d97706 | Colour of a warning annotation. |
--c2-chart__annotation__danger--color | color | #dc2626 | Colour of a danger annotation. |
--c2-chart__annotation-range--opacity | opacity | 0.12 | Opacity of the shaded fill of a range annotation. |
--c2-chart__annotation-line--border-width | pixel | 1px | Width of an annotation's rule. |
--c2-chart__annotation-line--border-style | border-style | dashed | Style of an annotation's rule. |
--c2-chart__annotation-marker--size | pixel | 10px | Diameter of an annotation's marker. |
--c2-chart__annotation-marker--border-color | color | #ffffff | Ring drawn around a marker, so it stands out from the bars or lines behind it. |
--c2-chart__annotation-marker__focus--outline | outline | 2px solid #0265dc | Focus ring of a marker. |
--c2-chart__state--color | color | #71717a | Colour of the empty, loading and error text. |
--c2-chart__state--font-size | font-size | 14px | Font size of the empty, loading and error text. |
c2-chart-series
One series of a chart, declared as a light-DOM child. The element renders nothing: it is a definition
the chart reads, the same way c2-table reads its c2-table-column children. Everything it exposes as
an attribute can also be set as a property, and format is property-only.
<c2-line-chart x-field="month" data='[{ "month": 1, "revenue": 120, "cost": 80 }]'>
<c2-chart-series field="revenue" label="Revenue"></c2-chart-series>
<c2-chart-series field="cost" label="Cost" color="#ea580c"></c2-chart-series>
</c2-line-chart>
Attributes
| Name | Type | Default | Description |
|---|---|---|---|
field | string | — | Key of the value in the row object; may be a dotted path such as stats.cpu. |
label | string | undefined | — | Legend and tooltip label. Falls back to the field name. |
color | string | undefined | — | Explicit colour. Falls back to this series' slot in the chart's palette. |
line-width | number | undefined | — | Stroke width in pixels. Falls back to --c2-chart__line--width. |
axis | 'left' | 'right' | left | Which y axis the series is drawn against. |
span-gaps | boolean | false | Joins across gaps instead of breaking the line. |
hidden | boolean | false | Leaves the series out of the chart without removing the definition. |
c2-chart-legend
A legend linked to a chart by id. Place it anywhere in the document to control the legend's layout independently from the chart.
Attributes
| Name | Type | Default | Description |
|---|---|---|---|
for | string | — | Id of the chart this element presents. |
Slots
| Name | Description |
|---|---|
(default) | Replaces the generated legend. Use renderLegend or renderLegendItem for data-driven custom content. |
CSS parts
Shadow DOM styling hooks used with ::part(name). Prefer CSS custom properties when they cover the change.
| Name | Description |
|---|---|
item | One interactive legend entry. |
marker | The colour swatch inside an entry. |
CSS custom properties
Grouped by semantic target and state from --c2-<component>__<target>__<state>--<property>. Click a group to collapse it; click a name to copy it.
| Name | Type | Default | Description |
|---|---|---|---|
--c2-chart__legend--gap | pixel | 12px | Gap between legend entries. |
--c2-chart__legend--padding | padding | 0 | Padding around the legend. |
--c2-chart__legend--color | color | #71717a | Legend text colour. |
--c2-chart__legend--font-size | font-size | 12px | Legend font size. |
--c2-chart__legend__disabled--opacity | opacity | 0.38 | Opacity of a disabled entry. |
--c2-chart__legend-marker--size | pixel | 10px | Size of the colour swatch. |
--c2-chart__legend-marker--border-radius | border-radius | 999px | Radius of the colour swatch. |
c2-chart-tooltip
A tooltip linked to a chart by id. It can float beside the hovered point or render inline wherever it is placed in the document.
It is shown only while its chart has a hovered point, and says so through the custom state :state(open) rather
than by toggling hidden on itself: the host keeps exactly the attributes it was authored with, so a
server-rendered tooltip matches the hydrated one. An authored hidden still hides it.
Attributes
| Name | Type | Default | Description |
|---|---|---|---|
position | 'floating' | 'inline' | floating | Whether the tooltip follows the hovered point or occupies its authored HTML position. |
placement | 'top' | 'bottom' | 'start' | 'end' | top | Preferred side of the hovered point when position="floating". Flips at viewport edges. |
for | string | — | Id of the chart this element presents. |
Slots
| Name | Description |
|---|---|
(default) | Replaces the generated tooltip body. Use renderTooltip for data-driven custom content. |
CSS parts
Shadow DOM styling hooks used with ::part(name). Prefer CSS custom properties when they cover the change.
| Name | Description |
|---|---|
bubble | The tooltip surface. |
CSS custom properties
Grouped by semantic target and state from --c2-<component>__<target>__<state>--<property>. Click a group to collapse it; click a name to copy it.
| Name | Type | Default | Description |
|---|---|---|---|
--c2-chart__tooltip--background-color | color | #18181b | Tooltip background. |
--c2-chart__tooltip--color | color | #fafafa | Tooltip text colour. |
--c2-chart__tooltip--font-size | font-size | 12px | Tooltip font size. |
--c2-chart__tooltip--padding | padding | 8px 10px | Tooltip padding. |
--c2-chart__tooltip--border-radius | border-radius | 6px | Tooltip corner radius. |
--c2-chart__tooltip--box-shadow | box-shadow | 0 8px 24px rgba(24, 24, 27, 0.08) | Tooltip shadow. |
--c2-chart__tooltip--gap | pixel | 6px | Gap between tooltip rows. |
--c2-chart__legend-marker--size | pixel | 10px | Size of the colour swatch in a tooltip row. |
--c2-chart__legend-marker--border-radius | border-radius | 999px | Corner radius of a tooltip row's colour swatch. |