Skip to content

Gauge

A radial dial for a single value — with threshold zones, an optional needle, ticks, and a target.

Stablev0.4.2added in v0.2.0@garn/ui/gauge
On this page

Default

A full-ring dial with a centre readout.

Thresholds

Threshold zones auto-colour the arc + reading; a target tick.

Needle

A half-circle speedometer with ticks + scale.

Sizes

sm / md / lg, with a delta.

Installation

garn is copy-in — the garn CLI writes this component's source into your project, so you own and can edit it. It resolves any base files and installs the npm dependencies below for you.

terminal
npx garn-ui add gauge
First time? Set up garn in your project
Registry
gauge
Deps
d3-shaped3-scale
Registry deps
utils

Import

import { Gauge } from "@garn/ui/gauge";

Props

The component's public props and their types.

color
Description
Single-tone fallback when there are no `thresholds`. Token reference.
Type
string
Default
"var(--garn-chart-1)"
delta
Description
Optional trend readout under the value (e.g. a delta).
Type
React.ReactNode
endAngle
Description
Arc end in degrees, clockwise from 12 o'clock.
Type
number
Default
135
label
Description
Caption under the value (e.g. the metric name).
Type
React.ReactNode
max
Description
High end of the scale.
Type
number
Default
100
min
Description
Low end of the scale.
Type
number
Default
0
numberFormat
Description
`Intl.NumberFormat` options for the value and scale labels.
Type
Intl.NumberFormatOptions
showScale
Description
Show min / max end labels on the scale.
Type
boolean
Default
false
showValue
Description
Show the centre value readout.
Type
boolean
Default
true
size
Description
Dial size.
Type
"lg" | "md" | "sm"
Default
"md"
startAngle
Description
Arc start in degrees, clockwise from 12 o'clock (default sweep is a 270° dial).
Type
number
Default
-135
target
Description
A reference marker on the arc; folded into the accessible reading.
Type
number | { value: number; label?: string; }
thresholds
Description
Colour zones — auto-colour the arc + reading, and draw the track bands.
Type
GaugeThreshold[]
ticks
Description
Number of tick intervals around the arc (0 = none).
Type
number
Default
0
valueRequired
Description
The current reading; clamped into `[min, max]` for the arc and the announced value.
Type
number
valueLabel
Description
Overrides the centre readout — use when the number needs custom formatting or a unit.
Type
React.ReactNode
variant
Description
Filled progress arc, or a speedometer needle over the zones.
Type
"arc" | "needle"
Default
"arc"

Plus 279 inherited native <div> attributes.

Styling

Target these data-slots and states, and remap these tokens, to restyle without forking the component.

[data-slot="gauge"]

When to use

Show a single value on a dial against thresholds/target — capacity, score, throughput, health.

Reach for something else when

  • Comparing many KPIs or fitting a dense table (use Bullet)
  • simple linear progress (use Progress)
  • a trend (use Sparkline).

Overview

Gauge is the KPI dial: a single value on a radial scale, read against optional threshold zones (calm → warning → critical) that colour the arc and the accessible reading. It shows as a filled arc or a speedometer needle, with optional ticks, a scale, and a target marker. It's pure d3-shape SVG — no charting engine — and a meter for assistive tech, so the value is announced.

Guidelines

Use it for one prominent value. A gauge earns its space as a single, glanceable dial; to compare many KPIs or fit a table, a Bullet is denser. For simple linear progress, Progress is lighter.

Let zones do the colouring. Pass thresholds and the arc auto-colours by the active zone and folds the zone label into the reading — don't hand-set color per value. Zones double-encode as bands so the state reads without relying on hue.

Announce the value. It's a meter: give it an aria-label; the value, active zone, and target are folded into aria-valuetext.

Best practices

Do
  • Pass thresholds for auto-zone colouring; give it an aria-label.
  • Use variant="needle" for a speedometer; set target for a reference.
Don't
  • Don't hand-colour per value when zones express the meaning.
  • Don't line up many gauges where bullets would compare better.

Troubleshooting

aria-valuenow sits outside [min,max].

Cause. The value exceeds the bounds.

Fix. It's clamped for aria; the readout can still show the raw value via valueLabel.

Needle reads oddly on a full ring.

Cause. Needle suits ≤270° sweeps.

Fix. Use the default arc for full rings; needle for half/three-quarter dials.

Accessibility

Role
meter
A1.4.1Use of ColorA4.1.2Name, Role, Value
  • role=meter with aria-valuenow (clamped into [min,max]) / aria-valuemin / aria-valuemax; pass an `aria-label`.
  • aria-valuetext folds in the value, the active zone label, and the target (e.g. "94%, Critical, target 80").
  • The centre readout + SVG are decorative; zone colour is paired with the zone label so meaning isn't colour-only.