Gauge / Speedometer
ProHalf-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.
import { SvGaugeChartComponent } from '@styloviz-pro/charts';Demo & usage
Basic usage
ProUsage example — open the gallery for the full interactive demo.
An interactive demo for this component lives in the gallery.
Open live demoMore examples
Range bands & needle
ProA target to read against
ProCustom reference wording
ProWhen 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
| Name | Type | Default | Description |
|---|---|---|---|
| value | number | null | null | The 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. |
| min | number | 0 | Minimum value of the scale. |
| max | number | 100 | Maximum value of the scale. |
| label | string | '' | Caption shown under the value. |
| suffix | string | '%' | Unit appended to the value (e.g. %). |
| variant | GaugeVariant | 'arc' | Gauge style variant. |
| size | number | 220 | Overall diameter in pixels. |
| thickness | number | 20 | Arc thickness in pixels. |
| ranges | readonly GaugeRange[] | [ { from: 0, to: 33, color: 'var(--colo… | Colored threshold bands along the scale. |
| target | number | null | null | A 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. |
| targetLabel | string | 'Target' | Wording for the reference marker. |
| showNeedle | boolean | true | Show the value needle. |
| animated | boolean | true | Animate the arc/needle on value change. |
| ariaLabel | string | '' | Accessible name override. Falls back to a generated value/range summary. |
| customClass | string | '' | Extra CSS classes applied to the root wrapper. |
| loading | boolean | false | True while the reading is being fetched. |
| error | SvDataError | string | null | null | Load failure. A bare string is accepted; use `toSvDataError()` to normalize an `HttpErrorResponse` and get sensible retry behaviour. |
| emptyMessage | string | 'No reading available' | Copy for the empty state. |
| filtered | boolean | false | Distinguishes "no reading at all" from "nothing matched the current filters". |
Outputs
| Event | Payload type | Description |
|---|---|---|
| selected | GaugeSelectEvent | Emitted when the gauge is clicked or activated via keyboard (Enter/Space). Named `selected` rather than `select`, which is a native DOM event name. |
| retry | void | The 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
ProBound to the names this component actually exposes.
Host class
ProDrive 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.