Gauge / Speedometer

Pro

Half-circle gauge with colored range bands, animated progress arc, needle, tick marks, an optional target notch and configurable min/max. The active band and the distance to the target are written out, not left to colour. Pure SVG.

</>sv-gauge-chart chartgaugekpi
import { SvGaugeChartComponent } from '@styloviz-pro/charts';

Demo & usage

Basic usage

Pro

Usage example — open the gallery for the full interactive demo.

Pro

An interactive demo for this component lives in the gallery.

Open live demo

More examples

Range bands & needle

Pro

A target to read against

Pro

Custom reference wording

Pro

When to use

  • Showing a single value against a range with a "good/warning/critical" feel.
  • KPIs like utilization, score, speed or health where thresholds matter.
  • For a plain percentage with no bands, a Progress Ring is simpler.

Async states

  • loading
  • empty
  • error
  • retry

Inputs

NameTypeDefaultDescription
valuenumber | nullnullThe current reading, or `null` when the metric has none — which is what the gauge's empty state means. Defaults to `null`, NOT to a number. It used to default to `72`, so an unbound gauge drew a confident three-quarter arc of nothing: a dashboard that failed to load its metric was indistinguishable from one at 72 %. Demo readings belong in the showcase, which binds `[value]` on every instance.
minnumber0Minimum value of the scale.
maxnumber100Maximum value of the scale.
labelstring''Caption shown under the value.
suffixstring'%'Unit appended to the value (e.g. %).
variantGaugeVariant'arc'Gauge style variant.
sizenumber220Overall diameter in pixels.
thicknessnumber20Arc thickness in pixels.
rangesreadonly GaugeRange[][ { from: 0, to: 33, color: 'var(--colo…Colored threshold bands along the scale.
targetnumber | nullnullA target or reference the reading is meant to be measured against. A gauge without one shows a number and a colour, and the reader has to already know what good looks like. The target is drawn as a notch on the scale and stated in words beside the reading, with the distance to it — "8 below target" is the sentence a dashboard is usually being read for. `null` (the default) draws nothing at all: an invented target would be worse than none. A target off the scale is still measured against as bound; its marker is pinned to the end of the scale and a line under the reading says so. Every variant draws the marker.
targetLabelstring'Target'Wording for the reference marker.
showNeedlebooleantrueShow the value needle.
animatedbooleantrueAnimate the arc/needle on value change.
ariaLabelstring''Accessible name override. Falls back to a generated value/range summary.
customClassstring''Extra CSS classes applied to the root wrapper.
loadingbooleanfalseTrue while the reading is being fetched.
errorSvDataError | string | nullnullLoad failure. A bare string is accepted; use `toSvDataError()` to normalize an `HttpErrorResponse` and get sensible retry behaviour.
emptyMessagestring'No reading available'Copy for the empty state.
filteredbooleanfalseDistinguishes "no reading at all" from "nothing matched the current filters".

Outputs

EventPayload typeDescription
selectedGaugeSelectEventEmitted when the gauge is clicked or activated via keyboard (Enter/Space). Named `selected` rather than `select`, which is a native DOM event name.
retryvoidThe host should re-run the failed load.

Wire it to your API

This component is headless about transport: it renders what you give it and reports what the user asks for. Nothing below requires @styloviz/data — drive it from whatever you already use.

Template

Pro

Bound to the names this component actually exposes.

Host class

Pro

Drive the three async inputs from your own fetch.

  • This component does not emit a query, so it renders what you give it. Fetch on your own trigger and bind `ranges`, `loading` and `error`.
  • Set `filtered` when a search or filter is active. It is the difference between "you have no orders" and "no orders match this filter" — telling a customer with 4,000 orders the first one reads as a bug.
  • Normalize failures with `toSvDataError()` from `@styloviz/core`. It derives `retryable` from the status, so a 404 does not get a "Try again" button that can only fail again.

Full walkthrough: Connecting to a backend.

Customization & theming

  • Colored range bands and thresholds, with the active band named in text under the reading.
  • An optional `target` notch on the scale, with the distance to it stated in words and `targetLabel` for the wording. Every variant draws the marker. A target outside the scale is still measured against as bound — 40 against 500 on a 0–100 scale is "460% below target", not "60% below" a pinned 100 — while its marker is pinned to the end of the scale and a line under the reading, repeated in the accessible name, says the target is off the scale.
  • Needle and tick customization.
  • Animated arc with reduced-motion fallback.
  • Responsive: all three variants scale down to fit narrow containers (`max-w-full h-auto`) while keeping their aspect ratio, instead of overflowing at their fixed `size`.

Best practices

  • Do: Define `ranges` so the colored bands map to real thresholds.
  • Do: Always render the numeric value as text alongside the arc.
  • Don't: Don't use a gauge for multiple values — it shows exactly one.
  • Do: Give it a target whenever one exists. Without a reference the gauge shows a number and a colour, and the reader has to already know what good looks like; with one it draws a notch on the scale and states the distance — "8% below target" is the sentence a dashboard is usually being read for.
  • Do: Declare `ranges` in VALUE units, the same units as `min` and `max`. They are not percentages. A band written as 0-100 on a 0-200 gauge covers the bottom half of the scale, not all of it.
  • Don't: Do not rely on the band colours to carry the status. Red, amber and green are nothing to a screen reader, unreliable for a reader with a colour-vision deficiency, and gone in print — which is why the band label is written under the reading and belongs in every band you declare.

Accessibility

  • The gauge is `role="img"` with a generated value/range summary (override via `ariaLabel`), and is keyboard-focusable.
  • Animations honour `prefers-reduced-motion`; Enter/Space (or click) emits `select` with the current value, the active range and the target. Range thresholds are described, not color-only.
  • The active band is written out under the reading, and so is the distance to the target. The band colours carry their whole meaning in hue, which is nothing to a screen reader, unreliable for a reader with a colour-vision deficiency, and gone in print; the target notch is a mark on an arc and has nothing to say either, so both travel in the accessible name as well.

Feedback on Gauge / Speedometer

Spotted a gap in this page, or something that didn't work as described? Comments are GitHub Discussions in the public styloviz/community repo, so posting needs a GitHub account.

Loads giscus.app and GitHub — nothing is fetched until you click.