- ds
- Data display
- Chart frame
Chart frame
The parts every chart shares: head, legend, axes, tooltip.
Every chart in ds shares one frame: a head with what is measured and the headline number, an optional legend, the plot, and sometimes a foot. The parts are the same whether the plot holds lines, columns or points, so a dashboard reads as one thing.
Rows ingested
412k rows/s at peak
- kafka → bronze
Show code
<figure class="chart boxed">
<figcaption class="ch-head">
<div>
<p class="ch-title">Rows ingested</p>
<p class="ch-v">412k <small>rows/s at peak</small></p>
</div>
<ul class="ch-legend"><li class="s3">kafka → bronze</li></ul>
</figcaption>
<div class="plot" style="--h:9rem" role="img" aria-label="Rows ingested per second today">
<div class="ch-grid"><i style="--at:0" data-v="0"></i><i style="--at:0.5" data-v="500"></i><i style="--at:1" data-v="1k"></i></div>
<svg viewBox="0 0 100 100" preserveAspectRatio="none" aria-hidden="true"><path class="ch-fill s3" d="M0 89.2C0.71 89.27 1.42 89.4 2.13 89.4C2.84 89.4 3.55 89.1 4.26 89.1C4.96 89.1 5.67 89.26 6.38 89.3C7.09 89.34 7.8 89.4 8.51 89.4C9.22 89.4 9.93 89 10.64 89C11.35 89 12.06 89.2 12.77 89.2C13.48 89.2 14.18 88.66 14.89 88.6C15.6 88.54 16.31 88.5 17.02 88.5C17.73 88.5 18.44 88.5 19.15 88.5C19.86 88.5 20.57 88.17 21.28 87.9C21.99 87.63 22.7 87.22 23.4 86.7C24.11 86.18 24.82 85.23 25.53 84.5C26.24 83.77 26.95 83.19 27.66 82.3C28.37 81.41 29.08 80.34 29.79 78.9C30.5 77.46 31.21 74.92 31.91 73C32.62 71.08 33.33 69.49 34.04 67.4C34.75 65.31 35.46 62.76 36.17 60.3C36.88 57.84 37.59 55.49 38.3 52.6C39.01 49.71 39.72 45.06 40.43 42.7C41.13 40.34 41.84 39 42.55 37.2C43.26 35.4 43.97 33.4 44.68 31.9C45.39 30.4 46.1 29.27 46.81 28C47.52 26.73 48.23 25.08 48.94 24.3C49.65 23.52 50.35 23.31 51.06 22.6C51.77 21.89 52.48 20.86 53.19 19.8C53.9 18.74 54.61 16.7 55.32 16.1C56.03 15.5 56.74 15.49 57.45 14.9C58.16 14.31 58.87 11.6 59.57 11.6C60.28 11.6 60.99 16.2 61.7 16.2C62.41 16.2 63.12 14.6 63.83 14.6C64.54 14.6 65.25 19.34 65.96 20.4C66.67 21.46 67.38 21.48 68.09 22.6C68.79 23.72 69.5 28.6 70.21 29.6C70.92 30.6 71.63 30.48 72.34 31.5C73.05 32.52 73.76 36.77 74.47 39.3C75.18 41.83 75.89 44.36 76.6 46.7C77.3 49.04 78.01 51.29 78.72 53.4C79.43 55.51 80.14 57.43 80.85 59.4C81.56 61.37 82.27 63.3 82.98 65.2C83.69 67.1 84.4 69.22 85.11 70.8C85.82 72.38 86.52 73.62 87.23 74.9C87.94 76.18 88.65 77.64 89.36 78.5C90.07 79.36 90.78 79.66 91.49 80.5C92.2 81.34 92.91 83.47 93.62 83.9C94.33 84.33 95.04 84.34 95.74 84.7C96.45 85.06 97.16 85.82 97.87 86.3C98.58 86.78 99.29 87.17 100 87.6L100 100L0 100Z"/><path class="ch-line s3" d="M0 89.2C0.71 89.27 1.42 89.4 2.13 89.4C2.84 89.4 3.55 89.1 4.26 89.1C4.96 89.1 5.67 89.26 6.38 89.3C7.09 89.34 7.8 89.4 8.51 89.4C9.22 89.4 9.93 89 10.64 89C11.35 89 12.06 89.2 12.77 89.2C13.48 89.2 14.18 88.66 14.89 88.6C15.6 88.54 16.31 88.5 17.02 88.5C17.73 88.5 18.44 88.5 19.15 88.5C19.86 88.5 20.57 88.17 21.28 87.9C21.99 87.63 22.7 87.22 23.4 86.7C24.11 86.18 24.82 85.23 25.53 84.5C26.24 83.77 26.95 83.19 27.66 82.3C28.37 81.41 29.08 80.34 29.79 78.9C30.5 77.46 31.21 74.92 31.91 73C32.62 71.08 33.33 69.49 34.04 67.4C34.75 65.31 35.46 62.76 36.17 60.3C36.88 57.84 37.59 55.49 38.3 52.6C39.01 49.71 39.72 45.06 40.43 42.7C41.13 40.34 41.84 39 42.55 37.2C43.26 35.4 43.97 33.4 44.68 31.9C45.39 30.4 46.1 29.27 46.81 28C47.52 26.73 48.23 25.08 48.94 24.3C49.65 23.52 50.35 23.31 51.06 22.6C51.77 21.89 52.48 20.86 53.19 19.8C53.9 18.74 54.61 16.7 55.32 16.1C56.03 15.5 56.74 15.49 57.45 14.9C58.16 14.31 58.87 11.6 59.57 11.6C60.28 11.6 60.99 16.2 61.7 16.2C62.41 16.2 63.12 14.6 63.83 14.6C64.54 14.6 65.25 19.34 65.96 20.4C66.67 21.46 67.38 21.48 68.09 22.6C68.79 23.72 69.5 28.6 70.21 29.6C70.92 30.6 71.63 30.48 72.34 31.5C73.05 32.52 73.76 36.77 74.47 39.3C75.18 41.83 75.89 44.36 76.6 46.7C77.3 49.04 78.01 51.29 78.72 53.4C79.43 55.51 80.14 57.43 80.85 59.4C81.56 61.37 82.27 63.3 82.98 65.2C83.69 67.1 84.4 69.22 85.11 70.8C85.82 72.38 86.52 73.62 87.23 74.9C87.94 76.18 88.65 77.64 89.36 78.5C90.07 79.36 90.78 79.66 91.49 80.5C92.2 81.34 92.91 83.47 93.62 83.9C94.33 84.33 95.04 84.34 95.74 84.7C96.45 85.06 97.16 85.82 97.87 86.3C98.58 86.78 99.29 87.17 100 87.6"/></svg>
<div class="ch-x"><span style="--at:0">00:00</span><span style="--at:0.25">06:00</span><span style="--at:0.5">12:00</span><span style="--at:0.75">18:00</span><span style="--at:1">00:00</span></div>
</div>
<footer class="ch-foot"><span>Source: ingest-workers, 1 minute resolution</span><span>Updated 12:04</span></footer>
</figure>Head
The title says what is measured, in sentence case: "Rows ingested", not "INGESTION METRICS". Under it goes either the headline value (.ch-v, with the unit in small) or a sub-line with the unit and bucket (.ch-sub). Controls and the legend sit on the right and wrap under on a phone.
Legend
- p50
- p95
- p99
- prod 8.4k
- staging 1.2k
Code
<ul class="ch-legend lines"><li class="s6">p50</li><li class="s1">p95</li><li class="s2">p99</li></ul>
<ul class="ch-legend">
<li class="s1">prod <b>8.4k</b></li><li class="s2">staging <b>1.2k</b></li>
</ul>
<div class="ch-legend">
<button class="s1" aria-pressed="true">reads</button><button class="s2" aria-pressed="false">writes</button><button class="s3" aria-pressed="true">deletes</button>
</div>Squares for areas and bars, short lines (.lines) for line charts. A b holds a value. As buttons, items toggle a series: aria-pressed="false" leaves a hollow swatch and greys the name. .col stacks the legend beside a donut or in a tooltip.
Tooltip
- reads8,412/s
- writes3,104/s
Code
<div class="plot no-x" style="--h:7rem;--x:.42">
<div class="ch-grid"><i style="--at:0"></i><i style="--at:.5"></i><i style="--at:1"></i></div>
<div class="ch-cross"></div>
<i class="ch-dot s1" style="--x:.42;--y:.68"></i>
<i class="ch-dot s2" style="--x:.42;--y:.31"></i>
<div class="ch-tip" style="top:.25rem">
<span class="label">Tue 14 Oct, 13:30</span>
<ul class="ch-legend"><li class="s1"><span>reads</span><b>8,412/s</b></li><li class="s2"><span>writes</span><b>3,104/s</b></li></ul>
</div>
</div>One crosshair, a ringed dot per series, and a card with the time and every value. Values are mono and right-aligned so they line up. Past 62% of the width the tip flips to the left of the crosshair (.flip). src/scripts/hover.ts does all of this for any .plot with a data-hover attribute.
Empty, loading and error
Code
<div class="plot" style="--h:7rem">
<div class="ch-grid"><i style="--at:0" data-v="0"></i><i style="--at:.5" data-v=""></i><i style="--at:1" data-v=""></i></div>
<div class="ch-state"><b>No data in this range</b>The pipeline has not run since Friday.</div>
</div>
<div class="plot" style="--h:7rem">
<div class="ch-grid"><i style="--at:0"></i><i style="--at:.5"></i><i style="--at:1"></i></div>
<div class="ch-state"><span class="skeleton" style="width:9rem"></span><span>Loading 24 hours</span></div>
</div>
<div class="plot" style="--h:7rem">
<div class="ch-grid"><i style="--at:0"></i><i style="--at:.5"></i><i style="--at:1"></i></div>
<div class="ch-state err"><b>Could not load metrics</b>prometheus-0 timed out after 30 s.<button class="btn sm">Retry</button></div>
</div>The plot keeps its height and gridlines, and the state sits over it, so a dashboard does not jump when data arrives. Say why there is no data and what happens next.
| Class | On | What it does |
|---|---|---|
.chart | figure | The frame. .boxed adds a border and surface. |
.ch-head | figcaption | Title block on the left, legend and controls on the right. |
.ch-title / .ch-sub / .ch-v | p | What is measured; unit and bucket; the headline value with small for the unit. |
.ch-legend | ul, div | Series keys from --c. Modifiers: lines, col. Items can be buttons with aria-pressed. |
.ch-foot | footer | Source and freshness, in mono. |
.ch-state | div | Over the plot: b for the headline, then a line. .err turns the headline red. |
.s1 … .s6 / .c-ok .c-warn .c-down | any | Set --c to a series or status colour. Every chart part reads it. |
- A title on every chart, even on a dashboard of them.
- The source and the update time in the foot.
- The same series colour for the same thing across a page.
- Chart titles in caps, or with "chart" in them.
- A legend far from the plot.
- Spinners in place of the plot: keep the frame and gridlines.