Playground
A row of pixel blocks lit up to value. The whole bar changes colour at the warn and danger thresholds, and blocks light up in a quick cascade. When danger is below warn, low values are the bad ones, as with fuel or batteries.
Examples
Driven by a signal
<div data-signals:_shields="58" style="display: grid; gap: 16px; inline-size: min(100%, 22rem)">
<sb-meter label="Shields" unit="%" data-attr:value="$_shields" data-preserve-attr="value"></sb-meter>
<sb-slider label="Power to shields" unit="%" data-bind:_shields__prop.value></sb-slider>
</div>
Thresholds
<div style="display: grid; gap: 16px; inline-size: min(100%, 22rem)">
<sb-meter label="Cargo" value="40" unit="t" max="60" warn="45" danger="55"></sb-meter>
<sb-meter label="Fuel" value="12" unit="%" warn="30" danger="15" segments="20"></sb-meter>
<sb-meter label="Heat" value="92" unit="%" segments="8"></sb-meter>
</div>
Live from the server
<div data-signals="{_tm: {fuel: 100}}" data-init="@get('/demo/telemetry')" style="inline-size: min(100%, 22rem)">
<sb-meter label="Fuel" unit="%" warn="30" danger="15" segments="20" data-attr:value="Math.round($_tm.fuel)" data-preserve-attr="value"></sb-meter>
</div>
Accessibility
The bar is a role="meter" with min, max, value and a readable value text. The colour change is backed by the number, so tone never carries the meaning alone.
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-meter label="Shields" value="75" unit="%" style="--sb-meter-width: 13rem"></sb-meter>
<!-- 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/meter@190cce1d4a26/meter.js" integrity="sha384-n30+bBiZIN6gBXfnj8T4Fe0aX5r62jEXJqX53bCAs1x64dFKO3sTBN58keQ3n0Jq"></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.
| File | Original | gzip | brotli |
|---|---|---|---|
meter.js | 3.2 kB | 1.4 kB | 1.2 kB |
API reference
Props
| Attribute | Type | Default | Description |
|---|---|---|---|
value | number | 0 | Current value. |
min | number | 0 | Minimum. |
max | number | 100 | Maximum. |
segments | number | 12 | Number of blocks. |
warn | number | 70 | Warning threshold. Below danger means low values are bad (like fuel). |
danger | number | 90 | Danger threshold. |
label | string | "" | Caption. |
unit | string | "" | Unit after the value. |
show-value | boolean | true | Show the value. |
decimals | number | 0 | Decimals shown. |