Skip to content
Home Theme Gallery

Line chart

The custom element is <hui-line-chart>.

Overview

The area chart's drawing without the fill: one line per series, with optional dots at every point. bare turns it into a sparkline for a table row, which still carries its name and its data table.

Example

Two series, with dots
Source
<hui-line-chart index="month" label="Desktop and mobile visitors" curve="monotone" dots grid legend tick-length="3" margin="8 12" style="height:200px">
<script type="application/json">{"series":[{"key":"desktop","label":"Desktop"},{"key":"mobile","label":"Mobile"}],"rows":[{"month":"January","desktop":186,"mobile":80},{"month":"February","desktop":305,"mobile":200},{"month":"March","desktop":237,"mobile":120},{"month":"April","desktop":73,"mobile":190},{"month":"May","desktop":209,"mobile":130},{"month":"June","desktop":214,"mobile":140}]}</script>
</hui-line-chart>

The Go template that renders it:

<hui-line-chart index="month" label="Desktop and mobile visitors" curve="monotone" dots grid legend tick-length="3" margin="8 12" style="height:200px">
<script type="application/json">{{ .Traffic }}</script>
</hui-line-chart>

API

Attributes21
Attributes
NameTypeDefaultDescription
labelstring""Required. The chart's accessible name, and the caption of the data table.
indexstring"label"The row property that holds each category.
curve"natural" | "monotone" | "linear" | "step""natural"The interpolation between points: d3-shape's curves, as Recharts uses them. monotone never overshoots the data.
stroke-widthnumber2The line's width, in pixels.
dotsbooleanfalseA dot at every point, not only the active one.
gridbooleanfalseDashed gridlines at each value tick.
value-axisbooleanfalseValue labels along the left.
hide-category-axisbooleanfalseLeaves the category labels out and keeps everything else.
barebooleanfalseNo axes, no grid, no margin: a sparkline.
minnumber-The value axis' low end.
maxnumber-The value axis' high end. With grid, the lines space evenly across the fixed domain.
marginstring"8 0 0 0"The plot's margin in pixels, CSS order.
tick-marginnumber8Space between the plot and its labels.
tick-lengthnumber-Shortens axis labels to this many characters; the tooltip and table keep them whole.
tooltip"index" | "item" | "none""index"Every series at the category, the series nearest the pointer, or nothing.
indicator"dot" | "line" | "dashed""dot"The marker beside each tooltip row.
hide-tooltip-labelbooleanfalseLeaves the category heading out of the tooltip.
legendbooleanfalseA legend under the plot.
cursorbooleanfalseA vertical rule at the active category.
formatstring-Intl.NumberFormat options as JSON.
localestringthe document's langThe locale values are formatted in.
Properties21
Properties
NameTypeDefaultDescription
labelstringas <code>label</code>Reflects to the label attribute.
indexstringas <code>index</code>Reflects to the index attribute.
curve"natural" | "monotone" | "linear" | "step"as <code>curve</code>Reflects to the curve attribute.
strokeWidthnumberas <code>stroke-width</code>Reflects to the stroke-width attribute.
dotsbooleanas <code>dots</code>Reflects to the dots attribute.
gridbooleanas <code>grid</code>Reflects to the grid attribute.
valueAxisbooleanas <code>value-axis</code>Reflects to the value-axis attribute.
hideCategoryAxisbooleanas <code>hide-category-axis</code>Reflects to the hide-category-axis attribute.
barebooleanas <code>bare</code>Reflects to the bare attribute.
minnumberas <code>min</code>Reflects to the min attribute.
maxnumberas <code>max</code>Reflects to the max attribute.
marginstringas <code>margin</code>Reflects to the margin attribute.
tickMarginnumberas <code>tick-margin</code>Reflects to the tick-margin attribute.
tickLengthnumberas <code>tick-length</code>Reflects to the tick-length attribute.
tooltip"index" | "item" | "none"as <code>tooltip</code>Reflects to the tooltip attribute.
indicator"dot" | "line" | "dashed"as <code>indicator</code>Reflects to the indicator attribute.
hideTooltipLabelbooleanas <code>hide-tooltip-label</code>Reflects to the hide-tooltip-label attribute.
legendbooleanas <code>legend</code>Reflects to the legend attribute.
cursorbooleanas <code>cursor</code>Reflects to the cursor attribute.
formatstringas <code>format</code>Reflects to the format attribute.
localestringas <code>locale</code>Reflects to the locale attribute.
Events1
Events
NameDescription
hui-chart-focusThe reader moved to a category, by pointer or keyboard: its position, and the row as the server sent it. It bubbles and is composed. Announced, never stored: a host can mirror it elsewhere on the page.
Slots1
Slots
NameDescription
(default)One <script type="application/json"> holding series and rows. Replacing it, or its text, redraws the chart.
CSS custom properties2
CSS custom properties
NameDefaultDescription
--hui-chart-1 … --hui-chart-5the preset's violetSeries colours, by position, repeating after the fifth.
--hui-series-<key>-One series' colour, set from the host's stylesheet: --hui-series-mobile: var(--hui-chart-4). A colour field in the JSON wins over it.
::part() hooks13
::part() hooks
NameDescription
figureThe wrapper carrying role="figure" and the label.
plotThe <svg>, hidden from assistive technology.
gridThe gridlines group.
axis-xThe labels under the plot.
axis-yThe value labels beside it.
seriesOne group per series, with data-key.
markA dot at each point, when dots is set.
lineA series' line, with data-series-index.
active-dotThe 4px dot on the active point.
tableThe visually hidden data table.
tooltipThe tooltip, a manual popover.
legendThe legend row.
announcerThe visually hidden live region.

States

A sparkline in a list row

The bare line at the size of a list row: no axes or grid, its colour set by a CSS custom property, and its data still readable as a table.

A sparkline in a list row
Source
<div class="hui-item hui-item--muted" style="max-width:22rem">
<div class="hui-item__content">
<div class="hui-item__title">Desktop visitors</div>
<p class="hui-item__description" style="margin:0">January to June</p>
</div>
<hui-line-chart index="month" label="Desktop visitors, January to June" bare curve="monotone" style="width:96px;height:32px;flex:none;--hui-series-desktop:var(--hui-chart-2)">
<script type="application/json">{"series":[{"key":"desktop","label":"Desktop"}],"rows":[{"month":"January","desktop":186},{"month":"February","desktop":305},{"month":"March","desktop":237},{"month":"April","desktop":73},{"month":"May","desktop":209},{"month":"June","desktop":214}]}</script>
</hui-line-chart>
<span style="font-weight:500">1,224</span>
</div>

Server-side mechanics

The server writes the series and rows as JSON into the element's <script type="application/json"> child, in the order they are drawn - the chart never sorts, filters or aggregates. html/template escapes a Go value into that script: {{ .Chart }}. Replacing the child redraws the same element without animating; replacing the element draws the new one. Nothing the reader did survives a swap.

Accessibility

  • The chart is a figure named by label, and its data is a visually hidden table with that label as its caption; the SVG is hidden from the accessibility tree.
  • The plot is one tab stop: the arrow keys step the points with the tooltip following, and a polite live region reads each move.
  • A null breaks the line rather than joining across a missing value, and reads "No data" in the tooltip and table.
  • Under forced colours lines draw in CanvasText, each series after the first with its own dash pattern.
  • The first draw reveals left to right over 1500ms; under prefers-reduced-motion: reduce it is simply there, and no redraw after a swap animates.

Keyboard

Keyboard
KeysAction
TabFocuses the plot, one stop per chart, and shows the tooltip at the category the keyboard was last on.
Arrow Right, Arrow DownThe next category.
Arrow Left, Arrow UpThe previous category.
Home, EndThe first and the last category.
EscapeHides the tooltip; focus stays on the plot.

Gotchas

  • A sparkline still needs a label: a row's trend is information, and the label names its table.
  • Like every chart, it ships in home-ui-charts.js, not home-ui.js.