Gauge

Composable SVG gauge primitives: arcs, zones, needles, ticks, dots, tooltips and a slider control. A Vue port of gauge-ui.

Default

Compose a gauge from primitives: a track, an arc and the value. Everything is plain SVG, so any SVG attribute or Tailwind class works on it.

Dark previewReplay previewOpen in new tab
72

Usage

Import the parts you need from the component's folder.

ts
import {
  Gauge,
  GaugeTrack,
  GaugeArc,
  GaugeValue,
} from "@/components/ui/gauge";

Half gauge

Set startAngle and endAngle for any sweep, and fit="content" so the box hugs the arc and fills the width you give it.

Dark previewReplay previewOpen in new tab
64Capacity

Needle styles

Four needle shapes: line, pointer, compass and arrow. Add GaugeHub for the pivot.

Dark previewReplay previewOpen in new tab
line
pointer
compass
arrow

Zones

Coloured bands between cutoffs, with optional gaps and round caps, behind a needle.

Dark previewReplay previewOpen in new tab

Stack

Split the fill into parts that sweep as one, by weight or by fixed cutoffs.

Dark previewReplay previewOpen in new tab
82%

Ticks and labels

Evenly spaced ticks, numeric labels and a needle make a speedometer.

Dark previewReplay previewOpen in new tab
0306090120150180210240

Marks

Cut the ring into equal segments, here ten glasses, by drawing marks in the surface colour over a band.

Dark previewReplay previewOpen in new tab
6

Progress ring with a dot

A full 360° ring with a dot that rides the arc, and an optional halo that stands it off the band.

Dark previewReplay previewOpen in new tab
0

Tooltip

Hover, press or focus the gauge. The bubble is portalled to the body and flips to stay on screen.

Dark previewReplay previewOpen in new tab

Slider control

GaugeControl makes the gauge a slider: drag the ring, or use arrow keys, Page Up and Down, Home and End.

Dark previewReplay previewOpen in new tab
35

Knob

With knob, a drag anywhere on the face turns the value by as far as the pointer goes round.

Dark previewReplay previewOpen in new tab

Inset gauge

A whole gauge inside another, with its own value and domain, like a fuel dial under a speedometer.

Dark previewReplay previewOpen in new tab

Compass

wrap treats the domain as a closed ring so a heading crossing north takes the short way, and compassLabel names the points.

Dark previewReplay previewOpen in new tab
NNEESESSWWNW

Transitions

A gentle spring by default, a bouncy spring, a timed tween with an easing curve, or no transition at all.

Dark previewReplay previewOpen in new tab
25
Spring
25
Bouncy spring
25
Tween
25
Instant

Centred dial

Anchor the arc at zero with from, so values below and above grow in opposite directions.

Dark previewReplay previewOpen in new tab
-24

Bars: Default

Forty radial bars, painted with the rainbow gradient. The centre value rolls in as the gauge scrolls into view. Set variant="bars" on Gauge; no children are needed.

Dark previewReplay previewOpen in new tab

Bars: Solid colour

Any CSS colour: hex, oklch(), or currentColor to follow the text colour.

Dark previewReplay previewOpen in new tab

Bars: Tailwind gradient classes

Pass from-*, via-* and to-* classes. The browser resolves the gradient, so any Tailwind v4 colour works.

Dark previewReplay previewOpen in new tab

Bars: Tailwind background class

A single bg-* class paints every bar with its computed colour, theme tokens included.

Dark previewReplay previewOpen in new tab

Bars: CSS variables

var(--chart-1), var(--color-amber-500) or any custom property, resolved per theme.

Dark previewReplay previewOpen in new tab

Bars: CSS gradient

A full linear-gradient() string, with explicit angles and stop positions.

Dark previewReplay previewOpen in new tab

Bars: Colour list

An array of colours is spread evenly along the sweep.

Dark previewReplay previewOpen in new tab

Bars: OKLCH stops

[position, L, C, H] stops are interpolated per bar, with no browser round trip, so they render on the server.

Dark previewReplay previewOpen in new tab

Bars: Function

Return a colour for each bar from its position t (0 to 1) and index.

Dark previewReplay previewOpen in new tab

Bars: Remaining

Show max minus value in the centre with show-remaining.

Dark previewReplay previewOpen in new tab

Bars: Number formats

Add a suffix, keep compact notation, or print the exact number with a locale.

Dark previewReplay previewOpen in new tab

Bars: Custom track

Colour the unlit bars with trackColor.

Dark previewReplay previewOpen in new tab

Bars: Transitions

Bars and number share one animated value, so they always move together. Pass a spring, a tween, or false for none.

Dark previewReplay previewOpen in new tab

Bars: Live value

Bars and number follow a changing value on the same spring.

Dark previewReplay previewOpen in new tab

Example: Monitor

A server monitor: load, temperature and fan on needle tiles, a CPU dial with a ring per core, memory and swap on one ring, network on a twin half dial, disk volumes and a top-style process list.

Dark previewReplay previewOpen in new tab

Example: Health

A day in a health app: activity rings with the week beside them, live heart rate over its training zones, last night's sleep round a 24-hour dial, steps and water filling to their goals, and vitals on their normal ranges.

Dark previewReplay previewOpen in new tab

Activity

Today
Move
420/600 kcal
Exercise
24/30 min
Stand
9/12 hr
This week
M
T
W
T
F
S
S

Heart rate

Now
40 BPM
Resting
58 bpm
Walking avg
94 bpm
Range
52–148
Zone
Rest
00061218

Sleep

23:10 – 06:52
121800067h 34masleep
Awake
0h 08m
REM
2h 04m
Core
4h 15m
Deep
1h 15m
In bed
7h 42m
23:1006:52

Steps

16:40
0of 10,000 steps
Distance
5.6 km
Flights
9 floors
To goal
2,158
Daily avg
8,910
00061218

Water

7 of 10 glasses
1.75 Lof 2.5 L
Remaining
0.75 L
Glass
250 ml
Last
14:20
Blood oxygen
98 %
Normal 95–100%
Respiratory rate
14.5 br/min
Normal 12–20
Heart rate variability
52 ms
Your range 38–64 ms
Cardio fitness
42.3 VO₂
VO₂ max, above average

Example: Time

World clocks for six cities, a chronograph stopwatch with laps, alarms on a 24-hour dial, and a bank of countdown timers.

Dark previewReplay previewOpen in new tab

World clock

121234567891011
San Francisco--:--
121234567891011
New York--:--
121234567891011
Reykjavík--:--
121234567891011
London--:--
121234567891011
Tokyo--:--
121234567891011
Sydney--:--

Stopwatch

6051015202530354045505503:49.87
  1. Lap 301:12.1803:34.05
  2. Lap 201:09.5302:21.87
  3. Lap 101:12.3401:12.34

Alarms

00061218--:--No alarms
  • 06:30Wake upWeekdays
  • 07:45Long runSat
  • 09:15Stand-upWeekdays
  • 22:30Wind downEvery day

Timers

Tea1:12 of 3:00
Pasta6:24 of 10:00
Focus18:40 of 25:00

Example: Weather

A Reykjavik afternoon: temperature over the hours ahead, a live wind vane, the sun's path, an aneroid barometer with its set hand, air quality and condition tiles.

Dark previewReplay previewOpen in new tab

Reykjavík

Sun 27 Sep · 14:20
-20°°C5° · 10°
Partly cloudy
Feels like
6°
Dew point
5°
Chance of rain
10%
Low · High
5° · 10°

Wind

From SE
NESW9m/s
Speed
9.0 m/s
Gusts
14 m/s
Bearing
135°
Beaufort
5, Fresh breeze
Now01:00

Sun

07:31 – 19:09
4h 49mof daylight left
Sunrise
07:31
Sunset
19:09
Daylight
11h 38m
Tomorrow
−6m 32s

Pressure

Falling
StormyRainChangeFairDry
Now
1003.6 hPa
3 h ago
1008.9 hPa
Change
-5.3 hPa
Outlook
Rain, wind

Air quality

Good
0AQI
PM2.5
4 µg/m³
PM10
9 µg/m³
O₃
52 µg/m³
NO₂
7 µg/m³
Humidity
74%
Comfortable 30–60%
Cloud cover
62%
5 of 8 oktas
UV index
2
Low
Visibility
42km
Clear

Example: Smart Home

A smart home you can turn: a thermostat per room, dimmers for the lights, a volume knob beside what is playing, the car charging to its limit, the grid leaning between export and import, and tiles for air, water and the washer.

Dark previewReplay previewOpen in new tab

Climate

HEATING TO10.0°Now 20.2°
Living room

Lights

0%
Living room
0%
Kitchen
Off
Bedroom
0%
Porch

Music

Living room · Kitchen
0
Volume
Low TideHalcyon Drift
1:12-2:22
Air quality
612 ppm
CO₂, fresh below 800
Humidity
44 %
Living room, 30–60%
Water
184 L
Today, of 250 L average
Washer
24 min
Washing · 23:14

EV charging

Wall box · 32 A
CHARGING0%307 km
Rate
7.4 kW
Added
0.0 kWh
Limit
80%
Ready
15:50

Energy

Importing 5.2 kW
1050510
ExportImport
Solar
3.4 kW
House
1.2 kW
Car
7.4 kW
Today
18.6 kWh made

Example: Dashboard

A twin-dial cluster: a tachometer with its redline band, and a speedometer with fuel closing its ring.

Dark previewReplay previewOpen in new tab

Example: Cockpit

The six-pack of a light aircraft: airspeed, attitude, altitude, turn coordinator, heading and vertical speed, flown by a toy autopilot.

Dark previewReplay previewOpen in new tab
406080100120140160180200KNOTS
20101020
0123456789ALT29.92
LRTURN COORDINATOR2 MINNO PITCHINFORMATION
N36E1215S2124W3033HDG270°
201510551015UPDNFT/MIN

API Reference

Gauge

PropTypeDefaultDescription
valuenumber—Current value (required). Clamped to the domain, or folded when wrap is on.
minnumber0Lower end of the domain.
maxnumber100Upper end of the domain.
startAnglenumber40Where the sweep starts, in degrees clockwise from six o'clock.
endAnglenumber320Where the sweep ends, in the same degrees.
radiusnumber200Reference radius in SVG units. Every child positions itself against it.
transitionGaugeTransition | booleanundefinedtrue for the default spring, a spring or tween config to tune it. Omit for instant updates.
initialValuenumberundefinedValue the gauge starts from on mount, for a sweep-in.
wrapbooleanfalseTreat the domain as a closed ring (compass, clock): values fold and animation takes the short way.
rotatenumber0Turn the whole scale this many degrees clockwise, animated by transition.
paddingnumber48Extra room around the reference circle for thick strokes, ticks and labels.
fit'square' | 'content'"square"square boxes the whole circle. content fits the box to the arc's own sweep.
variant'arc' | 'bars'"arc"arc composes primitives inside the SVG. bars draws a self-contained radial bar ring with a readout.
colorstring | string[] | [pos, L, C, H][] | (t, i) => stringrainbowbars variant: bar colour. A solid (hex, oklch, var(--x), bg-primary), Tailwind gradient classes, a CSS gradient, a list of colours, OKLCH stops or a function.
trackColorstring"var(--border)"bars variant: colour of the unlit bars.
centerValuenumber | stringnullbars variant: override the centre value.
centerLabelstring""bars variant: label under the centre value.
showMaxbooleanfalsebars variant: append /max to the centre value.
showRemainingbooleanfalsebars variant: use max - value as the centre value.
suffixstring""bars variant: small unit after the centre value, e.g. %.
totalBarsnumber40bars variant: number of radial bars.
compactbooleantruebars variant: compact notation (1.2K).
localesstringundefinedbars variant: number locale, e.g. en-US.
ariaLabelstring""bars variant: accessible name; defaults to centerLabel.
valueTextstringundefinedbars variant: spoken value for assistive tech.
animatedbooleannullbars variant: overrides the global chart animation switch.
SlotDescription
defaultGauge primitives.

GaugeInset

PropTypeDefaultDescription
valuenumber—Current value (required). Clamped to the domain, or folded when wrap is on.
minnumber0Lower end of the domain.
maxnumber100Upper end of the domain.
startAnglenumber40Where the sweep starts, in degrees clockwise from six o'clock.
endAnglenumber320Where the sweep ends, in the same degrees.
radiusnumber200Reference radius in SVG units. Every child positions itself against it.
transitionGaugeTransition | booleanundefinedtrue for the default spring, a spring or tween config to tune it. Omit for instant updates.
initialValuenumberundefinedValue the gauge starts from on mount, for a sweep-in.
wrapbooleanfalseTreat the domain as a closed ring (compass, clock): values fold and animation takes the short way.
rotatenumber0Turn the whole scale this many degrees clockwise, animated by transition.
xnumber0Centre of the inset in the host gauge's units.
ynumber0Vertical centre. Positive is down.
scalenumber1Size relative to the host gauge.
SlotDescription
defaultPrimitives drawn against the inset's own value and domain.

GaugeTrack

PropTypeDefaultDescription
widthnumber24Stroke width in SVG units.
colorstring"currentColor"Any CSS colour or variable.
opacitynumber0.15Stroke opacity.
cap'round' | 'butt'"round"Stroke line cap.
offsetnumber0Radial offset from the reference radius. Positive moves outward.

GaugeArc

PropTypeDefaultDescription
widthnumber24Stroke width in SVG units.
colorstring"currentColor"Any CSS colour or variable.
opacitynumber1Stroke opacity.
cap'round' | 'butt'"round"Stroke line cap.
offsetnumber0Radial offset from the reference radius. Positive moves outward.
fromnumberminDomain value the arc is anchored at.
tonumbervalueDomain value the arc ends at.
reversebooleanfalseGrow the arc back from the end of the sweep.
wrapbooleanfalseCarry the arc on round a closed ring instead of clamping it.

GaugeStack

PropTypeDefaultDescription
parts{ weight?, to?, color, opacity? }[]—Parts of the fill. Use weights or fixed cutoffs, not both.
widthnumber24Stroke width.
opacitynumber1Group opacity.
cap'round' | 'butt'"butt"Stroke line cap.
offsetnumber0Radial offset.
fromnumberminDomain value the stack starts at.

GaugeZones

PropTypeDefaultDescription
zones{ to: number, color: string }[]—Ordered cutoffs. The last zone always extends to max.
widthnumber8Band width.
opacitynumber1Band opacity.
cap'round' | 'butt'"butt"Cap on the joints between zones.
endCap'round' | 'butt'capCap on the two outer ends of the whole band.
gapnumber0Gap between neighbouring zones, in degrees.
offsetnumber0Radial offset.

GaugeTicks

PropTypeDefaultDescription
countnumber10Number of intervals; draws count + 1 ticks.
lengthnumber12Length of each line along the radius.
widthnumber2Stroke width.
colorstring"currentColor"Stroke colour.
opacitynumber1Stroke opacity.
cap'round' | 'butt'"round"Line cap.
offsetnumber0Radial offset of the line's midpoint.

GaugeMarks

PropTypeDefaultDescription
valuesnumber[]undefinedDomain values to mark.
countnumberundefinedCut the domain into this many equal segments; marks fall between them.
lengthnumber12Length of each line along the radius.
widthnumber2Stroke width.
colorstring"currentColor"Stroke colour.
opacitynumber1Stroke opacity.
cap'round' | 'butt'"round"Line cap.
offsetnumber0Radial offset of the line's midpoint.

GaugeTickLabels

PropTypeDefaultDescription
countnumber10Number of intervals.
offsetnumber-48Radial offset of the label centre.
fontSizenumber16Font size.
colorstring"currentColor"Label fill.
font'sans' | 'rounded' | 'mono'"sans"Font family class.
weightstring"medium"Font weight.
decimalsnumber0Decimals for the default formatter.
format(value: number) => stringundefinedCustom label, for example compassLabel.

GaugeText

PropTypeDefaultDescription
xnumber0Horizontal position from the centre.
ynumber0Vertical position from the centre. Positive is down.
fontSizenumber24Font size in SVG units.
colorstring"currentColor"Text fill.
font'sans' | 'rounded' | 'mono'"sans"Font family class.
weight'regular' | 'medium' | 'semibold' | 'bold'"medium"Font weight.
anchor'start' | 'middle' | 'end'"middle"Which edge of the text sits at its position.
SlotDescription
defaultThe text.

GaugeValue

PropTypeDefaultDescription
xnumber0Horizontal position from the centre.
ynumber0Vertical position from the centre. Positive is down.
fontSizenumber96Font size in SVG units.
colorstring"currentColor"Text fill.
font'sans' | 'rounded' | 'mono'"sans"Font family class.
weight'regular' | 'medium' | 'semibold' | 'bold'"semibold"Font weight.
anchor'start' | 'middle' | 'end'"middle"Which edge of the text sits at its position.
decimalsnumber0Decimals for the default formatter.
format(value: number) => stringundefinedCustom formatter, e.g. clockTime or durationLabel.

GaugeNeedle

PropTypeDefaultDescription
variant'line' | 'pointer' | 'compass' | 'arrow'"line"Needle shape.
lengthnumber0.85Length as a fraction of the reference radius.
widthnumber6Stroke width for line; width at the centre for filled shapes.
colorstring"currentColor"Needle colour.
tailnumber30How far the needle extends behind the centre.
tailColorstringcolorColour of the tail half.
tailDotnumber0Radius of a counterweight disc at the end of the tail.
turnsnumber1Sweeps across the domain, like a clock's minute hand.
gapnumber0Clear circle around the centre that splits the needle in two.

GaugeHub

PropTypeDefaultDescription
radiusnumber12Disc radius.
colorstring"currentColor"Disc colour.

GaugeDot

PropTypeDefaultDescription
radiusnumber10Dot radius.
colorstring"currentColor"Dot colour.
opacitynumber1Dot opacity.
offsetnumber0Radial offset from the reference radius.
turnsnumber1Sweeps across the domain.
halonumber0Width of a ring behind the dot. 0 leaves it bare.
haloColorstring"var(--background)"Colour of the halo.

GaugeControl

PropTypeDefaultDescription
modelValuenumber—Bound value (v-model).
minnumber0Lower end of the domain.
maxnumber100Upper end of the domain.
stepnumber1Granularity of a drag and of an arrow-key step.
startAnglenumber40Match the gauge drawn inside.
endAnglenumber320Match the gauge drawn inside.
labelstring—Accessible name of the slider (required).
valueTextstringundefinedThe value as it would be spoken.
knobbooleanfalseTurn the face like a knob instead of jumping to the pointer.
disabledbooleanfalseDisable pointer and keyboard input.
EventDescription
update:modelValueEmitted with the new value.
pressA press in the middle of the face, or Enter.
SlotDescription
defaultThe Gauge to control.

GaugeTooltip

PropTypeDefaultDescription
position'pointer' | 'value' | 'center' | 'top' | 'right' | 'bottom' | 'left' | 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'"value"What the bubble is pinned to.
side'auto' | 'center' | 'top' | 'right' | 'bottom' | 'left'"auto"Which way the bubble stands off its point.
atnumbervalueDomain value a value tooltip points at and shows.
offsetnumber24How far out from the reference radius the point sits.
gapnumber8Room between the point and the bubble, in pixels.
avoidCollisionsbooleantrueFlip and slide the bubble to keep it on screen.
collisionPaddingnumber8Room kept clear at the viewport edge.
openbooleanundefinedHold the tooltip open or shut instead of on hover, press and focus.
labelstring""Small line above the value.
unitstring""Printed after the value.
decimalsnumber0Decimals for the default formatter.
format(value: number) => stringundefinedCustom formatter.
bubbleClassstring""Classes merged onto the bubble.
SlotDescription
defaultReplaces the default content. Receives { value }.

Accessibility

Keyboard shortcuts and ARIA behavior.

Shortcut Description
← + ↓GaugeControl: decrease the value by one step.
→ + ↑GaugeControl: increase the value by one step.
Page Up + Page DownGaugeControl: move by a tenth of the domain.
Home + EndGaugeControl: jump to the minimum or maximum.
Enter + SpaceGaugeControl: emit press.
  • A gauge is an SVG: give it role="img" and an aria-label that states the reading, or wrap it in GaugeControl for a slider.
  • Animation snaps under prefers-reduced-motion.
  • variant="bars" renders role="meter" with aria-valuemin, aria-valuemax and aria-valuenow. Pass ariaLabel and valueText for a spoken reading.