Sparkline

A tiny stepped pixel chart that grows with every pushed value.

zweiundeins <sb-sparkline> chart trend telemetry dashboard Since 2026-09-21 2.4 kB0Open in playground Edit on GitHub

Playground

A small inline chart drawn as a stepped pixel line with a soft area underneath. Give it a JSON values array, or use push mode: the starting value is the first point, and every time the value attribute changes, a point is appended. The chart is always sized for length points, so its height is fixed from the start: fewer points spread across the width, and once it's full the line scrolls. Point value at a signal, and the line follows it as the signal ticks, from the client or from the server.

Examples

Push mode

data-on-interval changes a signal every 400 ms. data-attr pushes each new value into the chart.

<div data-signals:_alt="50" data-on-interval__duration.400ms="$_alt = Math.max(0, Math.min(100, $_alt + (Math.random() * 20 - 9)))">
  <sb-sparkline data-attr:value="$_alt" data-preserve-attr="value" show-value tone="accent" length="48" style="--sb-sparkline-width: 20rem"></sb-sparkline>
</div>

Static data

<sb-sparkline values="[3,5,4,8,6,9,12,10,14,13,17]" tone="ok" show-value></sb-sparkline>
<sb-sparkline values="[90,82,85,70,72,60,48,52,40,33,21]" tone="danger" show-value unit="%"></sb-sparkline>
<sb-sparkline values="[40,60,40,60,40,60,40,60]" scale="fixed" min="0" max="100" tone="brand"></sb-sparkline>

Live from the server

The server pushes $_tm.alt four times a second. Push mode turns every update into a new point.

<div data-signals="{_tm: {alt: 0}}" data-init="@get('/demo/telemetry')">
  <sb-sparkline data-attr:value="$_tm.alt" data-preserve-attr="value" length="80" show-value unit=" km" tone="accent" style="--sb-sparkline-width: 22rem"></sb-sparkline>
</div>

From JavaScript

el.push(n) appends a point, and el.data returns a copy of the buffer.

Accessibility

The canvas is role="img", and its label summarises the data (point count, latest, low and high). Use show-value when the latest number matters.

Installation

Add Datastar with Rocket and the Starbase autoloader once per page, then use the tag. The autoloader imports each component the first time its tag appears, including tags added later by a Datastar morph.

<!-- Once per page: Datastar with Rocket, and the Starbase autoloader.
     It loads every <sb-…> component the first time its tag appears. -->
<script type="importmap">
  { "imports": { "datastar": "https://cdn.jsdelivr.net/gh/starfederation/datastar@v1.0.4/bundles/datastar-rocket.js" } }
</script>
<script type="module" src="https://starbase.zweiundeins.gmbh/c/autoloader.js"></script>
<!-- Optional, no flash of undefined elements: class="sb-cloak" on <html>, and -->
<style>.sb-cloak :not(:defined) { visibility: hidden }</style>

<sb-sparkline values="[12,18,15,22,30,26,34,41,38,47,52,49,58,64,61,70]" length="16" tone="ok" show-value unit="%" style="--sb-sparkline-width: 12rem"></sb-sparkline>

<!-- In production, pin today's catalog instead of the latest: the browser then
     refuses any file that changed. Add "integrity" to the import map above: the
     hashes from https://starbase.zweiundeins.gmbh/c/@0a1ad1bf98a4/importmap.json and Datastar's, below. -->
<!--
<script type="importmap">
  { "imports": { "datastar": "https://cdn.jsdelivr.net/gh/starfederation/datastar@v1.0.4/bundles/datastar-rocket.js" },
    "integrity": { "https://cdn.jsdelivr.net/gh/starfederation/datastar@v1.0.4/bundles/datastar-rocket.js": "sha384-vUxZojLrF1Ar3de5h7VINqhJXBgjyZS4U49pHvGa87kum6j5Xn6JRziuARNw5ELG", "…": "…from importmap.json" } }
</script>
<script type="module" src="https://starbase.zweiundeins.gmbh/c/@0a1ad1bf98a4/autoloader.js" integrity="sha384-IvSCUjEWPS+wwXunU+48x96KmyWDx/Y4LeCwCL8cWFqJ/zHmTsTOsSMrzTOcpW3D"></script>
-->

<!-- Or load just this component, pinned to this version: -->
<!-- <script type="module" src="https://starbase.zweiundeins.gmbh/c/sparkline@df7b6708a734/sparkline.js" integrity="sha384-A/EIik3z83ZE+O/7hTiuoJkWzdRxIPxEj1CS6gqVlog4R0dcajncKkEb2XND45+4"></script> -->

Size

Each file compressed on its own, the way it is served (gzip -9, brotli -11). Datastar and Rocket are shared by every component and not counted.

FileOriginalgzipbrotli
sparkline.js 6.4 kB2.7 kB2.4 kB

API reference

Props

AttributeTypeDefaultDescription
valuesarray[]Initial data points, as a JSON array.
valuenumber0Push mode: every change appends a point.
lengthnumber40Points kept (older ones scroll off).
scale"auto" | "fixed""auto"auto fits the data; fixed uses min and max.
minnumber0Bottom of the fixed scale.
maxnumber100Top of the fixed scale.
tone"brand" | "ok" | "warn" | "danger" | "accent""brand"Line colour (theme token).
show-valuebooleanfalseShow the latest value next to the line.
unitstring""Unit after the shown value.
decimalsnumber0Decimals of the shown value.