# Chart

Draws a line, an area or a small trend line from a table or a list of numbers you already wrote, which stays in the page beside it.

### Known issues
Four things to know before you rely on it.

- Without `interactive` there is no readout on hover or focus: the figures are in the table, which the button shows. With it, the readout follows the pointer and the focus alike.
- It reads the table when it connects, when the table changes and when the box changes size. A table added to the page later, after the page loaded the script, needs the element to be added with it.
- The plot is drawn left to right in every language, as a time axis is; the table, the title, the legend and the button follow the page’s direction.
- It has not been tested with a screen reader.

### Copy the markup
Write the table first, as the page a reader lands on without JavaScript. The first column is the X axis, a `th` of its row; each other column is a series, named by its `th`. Put each number in a `<data value>` and write it as you want it read in the cell. Wrap the table in a `.luz-table-wrap` only when it can be wider than the screen, as the three-series example does, and give each `td` a `data-label` so that on a narrow screen its rows stack and still name their cells. A table that always fits needs no wrapper: with one, the group, the region and the table would read the same name three times. The chart hides the wrapper with the table, and it takes no Tab stop meanwhile.

`catalog.min.js` loads the element’s own file, `chart.min.js`, when it scans the page; a page without `catalog.min.js` loads that file on its own. Link `components/chart.css`, after core’s.

Chart markup
```html
<script type="module" src="https://cdn.jsdelivr.net/npm/@luz-ds/catalog@0.3.0/dist/catalog.min.js"></script>

<luz-chart type="line" data-luz-label-table="Show table" data-luz-label-chart="Show chart">
  <table class="luz-table">
    <caption>Parcels per route, January to March</caption>
    <thead>
      <tr><th scope="col">Month</th><th scope="col">Sevilla</th><th scope="col">Cádiz</th></tr>
    </thead>
    <tbody>
      <tr><th scope="row">Jan</th><td data-label="Sevilla"><data value="1204">1,204</data></td><td data-label="Cádiz"><data value="312">312</data></td></tr>
      <tr><th scope="row">Feb</th><td data-label="Sevilla"><data value="1310">1,310</data></td><td data-label="Cádiz"><data value="340">340</data></td></tr>
      <tr><th scope="row">Mar</th><td data-label="Sevilla"><data value="1180">1,180</data></td><td data-label="Cádiz"><data value="365">365</data></td></tr>
    </tbody>
  </table>
</luz-chart>
```

With `interactive`, a header of the series and their totals, and a readout of a day:

Interactive chart markup
```html
<luz-chart type="line" interactive data-luz-label-table="Show table" data-luz-label-chart="Show chart">
  <table class="luz-table">
    <caption>Visitors per day, April 1 to 3</caption>
    <thead>
      <tr><th scope="col">Day</th><th scope="col">Desktop</th><th scope="col">Mobile</th></tr>
    </thead>
    <tbody>
      <tr><th scope="row">Apr 1</th><td><data value="252">252</data></td><td><data value="148">148</data></td></tr>
      <tr><th scope="row">Apr 2</th><td><data value="271">271</data></td><td><data value="276">276</data></td></tr>
      <tr><th scope="row">Apr 3</th><td><data value="182">182</data></td><td><data value="128">128</data></td></tr>
    </tbody>
  </table>
</luz-chart>
```

A small line takes a list of `<data>` elements, in any markup, and shows the last of them:

Spark markup
```html
<luz-chart type="spark">
  <span>Parcels a day, last 4 days</span>
  <ul class="luz-chart__values" role="list">
    <li><data value="41">41</data></li>
    <li><data value="38">38</data></li>
    <li><data value="44">44</data></li>
    <li><data value="52">52</data></li>
  </ul>
</luz-chart>
```

Your scripts can ask what the chart would draw:

Script that reads the table
```js
import { readChart } from "@luz-ds/catalog/chart";

// What the chart draws: the names of the rows, and one series per column
const { rows, series } = readChart(document.querySelector("luz-chart"));
```

### Variants and options
- `<luz-chart>`: The custom element the module defines, around the table or the list. It wires itself when it connects
- `type`: `line` (the default) draws the table’s columns; `spark` draws one small line from the `<data>` elements inside. Anything else leaves the table
- `variant="area"`: Fills the area under each line, a light tint of the series colour
- `interactive`: With `type="line"` (or `type="column"` on a [column chart](https://nandovejer.github.io/luz/docs/catalog/column-chart/)): a header with a button per series, its name and total, which turns its line off and on, and a readout of the day under the pointer or the focus. It replaces the legend
- `data-luz-label-table`, `data-luz-label-chart`: The two words of the button: “Show table” and “Show chart”, in the page’s language, on the element or an ancestor (once on `<body>` serves every chart). LUZ has no English fallback: with either missing there is no button, and the table shows under the chart
- `--luz-chart-ratio`: The shape of the drawing, `2 / 1` by default. Set it on the element: `style="--luz-chart-ratio: 3 / 1"`
- `caption`: The title: the table’s caption names the group and is copied above the drawing
- `th scope="col"`: The name of a series, in the legend. The first column is the X axis; each other column is a series, up to six, and further ones stay in the table only
- `td` with `<data value>`: A number: the `value` of a `<data>`, or the plain text of the cell. Anything else is a gap in the line
- `.luz-chart__values`: The list of a `type="spark"`: the `<data>` elements are the points, and the last one shows as text
- `data-luz-view`, `data-luz-ready`, `data-luz-end`: Written by the script: `chart`, `table` or `both` for what shows; the element is ready; the last figure of a spark. Style them, never set them
- `readChart(el)`: Exported by `@luz-ds/catalog/chart`: the names of the rows and the series the table holds, or `null`

### How it works
CSS from `@luz-ds/catalog` and a file of its own, `@luz-ds/catalog/chart` (`dist/chart.min.js`, under 5 kB compressed), which defines `<luz-chart>`. It uses no library and draws with DOM calls only, so a page that forbids inline scripts and styles runs it as it is. To compare values by length with no script, use the [bar list](https://nandovejer.github.io/luz/docs/catalog/bar-list/), the [column chart](https://nandovejer.github.io/luz/docs/catalog/column-chart/), the [stacked bar](https://nandovejer.github.io/luz/docs/catalog/stacked-bar/) or the [heat map](https://nandovejer.github.io/luz/docs/catalog/heat-map/).

- **The table:** it stays in the page. While the chart shows, the table is moved off screen, not hidden, so a screen reader reads it as it always did; when the button shows the table, the drawing goes. On paper, the table prints and the drawing does not.
- **The drawing:** an SVG marked `aria-hidden`, drawn again when the box or the table changes. It has no animation. Series are `--luz-chart-1` to `--luz-chart-6`, so a change of mode repaints nothing.
- **Telling series apart:** each line ends in a mark of its own shape (a circle, a square, a triangle, a diamond, a plus and a cross), repeated in the legend. In forced colors every line is the text colour, each with its own dashes.
- **The numbers:** the scale starts at zero, or lower when a figure is negative, in round steps (1, 2 or 5 times a power of ten). The axes are written with `Intl.NumberFormat` in the page’s language, such as 1.2K.
- **Interactive:** the header has a toggle button per series, with its name and the sum of its figures. The total is a sum: it suits counts and amounts, such as visitors or euros, and not rates, shares or averages, whose total says nothing. A line turned off is not drawn, on the same scale, and the last line shown cannot be turned off. The day under the pointer, or the row with the focus, gets a light band and a readout with its name and the figure of each line shown, copied from the cells.
- **The words:** the script writes none of its own. The button’s two words are yours, in `data-luz-label-*`; the title and the legend copy your caption and your column heads.

### Without JavaScript
The table, or the list, is all there is, and it is complete: the caption, every figure, every name. The element is a block and the button does not exist. With `interactive` there is no header and no readout: every figure is in the table. It is the same when the page lacks the table, or `type` is not one of the two.

### Keyboard and ARIA
- **Keys:** Tab reaches the “Show table” button; Enter or Space presses it. Without `interactive` nothing in the picture takes the focus.
- **Interactive:** the buttons of the header are toggle buttons (`aria-pressed`): Enter or Space turns a line off and on, and the last line shown stays on. The picture then takes the focus, one Tab stop. It is a group named by the caption and holds a polite status that, on each key, says the label of the day, the same text as the row of the table. Each row is named by its own cells, from your text, “Apr 1, Desktop 252, Mobile 148”, every series, shown or not. With the focus on the picture, the arrow keys move to the next or the previous day (Right is always the next, as the plot is left to right), and Home and End to the first and the last; the keys of a screen reader’s browse mode are its own. Entering says its name and nothing else, and leaving empties the status.
- **The readout:** its title is the name of the day, so the band is never the only sign of where you are. Escape puts it away without moving the pointer or the focus; it comes back on another day. It is hidden from assistive technology, which reads the row. A line turned off is not drawn, but its cells stay in the table, read as before. The script writes the roles of the table (`table`, `rowgroup`, `row`, `columnheader`, `rowheader` and `cell`) so that the rows keep them in every browser.
- **Name:** the element is a group named by the table’s caption, and the button is described by it, so “Show table” is heard with what it shows. The drawing, its title and its legend are `aria-hidden`: the table says all of it.

### When to use
Use it to show how a few series change along an ordered axis, such as months, when the shape of the change is what the reader should see and you already have the numbers in a table. Add `interactive` for many days and two or more series, when the totals matter and a day is read one at a time. The small line (`type="spark"`) is for a figure that needs its trend beside it.

### When not to use
Do not use it when exact values matter more than the shape: a [table](https://nandovejer.github.io/luz/docs/components/table/) says them better. For a few values compared on one scale, use a [column chart](https://nandovejer.github.io/luz/docs/catalog/column-chart/) or a [bar list](https://nandovejer.github.io/luz/docs/catalog/bar-list/), which need no script.

- Do not use it for parts of a whole: use a [stacked bar](https://nandovejer.github.io/luz/docs/catalog/stacked-bar/). There is no pie or donut.
- Do not use `interactive` for rates, shares or averages: the total in its header is a sum.
- Do not use it for more than six series, or for series that cannot share a scale: split them into two charts.

It replaces a charting library that draws a canvas with no text beside it. Nothing in LUZ is removed.
