Skip to content

shadcn.io is an independent project built on shadcn/ui

Free

Gauge

One reading against its range, on an arc or a straight track. Needles, rulers, zones and glows are props, so a progress meter and a speedometer are the same component.

Charting library: TanStack Charts

Preview

Preview width

Installation

The command adds the example above to components/charts/ and, the first time, the chart kit to components/ui/charts/. Both are source files in your project from then on: read them, change them, delete what you don't use.

Sign in to get your install command
Free with an account. It carries your token, so the CLI installs everything in one go.

Usage

value is the fill, from 0 to 100. The number in the middle is a separate prop, centerValue, so a gauge filled to 66% can show revenue. Leave it out and there's no label.

<script setup lang="ts">
import { Gauge } from "@/components/ui/charts";
</script>

<template>
  <Gauge
    ariaLabel="Storage used"
    :center-value="72"
    default-label="Storage used"
    :inactive-fill-opacity="0.4"
    suffix="%"
    :value="72"
  />
</template>

Anatomy

The gauge is one component and every layer is a prop. The arc-only layers (ruler, needle, zones, sector, progress ring, dots, glow, center disc) claim room from the outside in, and the track shrinks to fit them.

<Gauge
  arc-style="solid"
  :center-value="78"
  default-label="Disk"
  needle="triangle"
  ruler
  suffix="%"
  :value="78"
  :zones="zones"
/>
  • Gauge: The track, the fill, the label and any dial layers you turn on.

Arcs and notches

startAngle and endAngle are in degrees, with 0 pointing right and angles running clockwise. The default 135 to 405 opens at the bottom, and 180 to 360 is the top half.

totalNotches (40), spacing (the share of the track left as gaps, 25%) and notchCornerRadius shape the notches. useGradient shades the lit ones across --chart-1 to --chart-5, or between the two colors of activeGradient.

Preview width

Linear gauges

orientation="linear" lays the notches along a straight track that fills its container. labelPlacement puts the label on any side of it and labelAlign at its start, center or end. linearHeight (24 px) sets the thickness.

The dial layers below are for arcs only. A linear gauge ignores them.

Preview width

Notches, a solid arc or no track

arcStyle="solid" swaps the notches for one rounded stroke, arcThickness thick. "none" drops the track altogether and leaves the value to a sector, a progress ring or dots.

Preview width

Rulers

ruler adds a scale of ticks inside the track that brightens up to the value. Pass options to move it outside with position, set ticks and majorEvery, and number it with labels: every major tick, the two "ends", or your own min, max and format.

Preview width

Needles

needle takes a variant, "line", "gradient", "triangle" or "polygon", or options. length is a fraction of the reach, and tip ends it inside the track, at its outer edge or past the outermost layer.

Preview width

Zones

zones marks ranges on the 0 to 100 scale, a red stretch past 85 for instance. By default each is a thin band around the track. zoneDisplay="fill" colors the fill itself where it crosses a zone, and "both" does both.

Preview width

Sectors, rings and dots

sector fills a wedge from the start to the value, with a conic or radial gradient or a flat color, which can be a pattern. progressRing adds a thin ring around the track, dots rings of dots that light up to the value, and glow a bloom on the fill.

centerDisc puts a ringed disc behind the label. Each takes true for its defaults or an options object.

Preview width

Customization

The kit is in your project, in components/ui/charts/: your framework's components over a shared core/. Change a default there and every chart picks it up.

class goes on the chart's container, so size and spacing are utility classes.

Children go into a hidden <defs>. Put a PatternLines or a gradient there and point activeFill, inactiveFill or a sector's color at it with url(#id). The ids are global to the page, so give each gauge its own.

<Gauge
  active-fill="url(#quota-stripes)"
  :inactive-fill-opacity="0.4"
  :value="64"
>
  <PatternLines
    :height="6"
    id="quota-stripes"
    :orientation="['diagonal']"
    stroke="var(--chart-1)"
    :stroke-width="1.5"
    :width="6"
  />
</Gauge>

Loading state

There's no loading state. Render the gauge at :value="0" until the reading arrives, and the fill sweeps up from zero when it does.

Animation

On mount the track fades in, then the fill sweeps up from zero on a spring with no bounce, lighting each notch as it passes. The needle, sector, ring and dots ride the same sweep.

A new value carries on from wherever the fill is, at the speed it already has, so a gauge fed every second never snaps back. enterTransition replaces the spring ({ type: "spring", visualDuration: 0.9, bounce: 0 }), and enterStaggerScale the pause before the sweep starts.

With reduced motion turned on, the gauge draws at its value with no sweep.

Preview width

Theming

Every color in the kit is one of your theme's tokens or a mix of them, except --chart-positive, a fixed green. A preset or the .dark class restyles the chart, and overriding a token in your CSS changes it everywhere.

Lit notches are --chart-1 and unlit ones your theme's --border at 80% opacity, unless you set activeFill and inactiveFill. With useGradient, the fill runs through the five chart colors.

Needles, rulers and the center disc's ring are drawn in --foreground, and a progress ring's remainder in --muted-foreground. Each has a prop to change it.

TokenDefaultPaints
--chart-1your theme'sthe first series
--chart-2your theme'sthe second series
--chart-3your theme'sthe third series
--chart-4your theme'sthe fourth series
--chart-5your theme'sthe fifth series
globals.css
:root {
  --chart-label: var(--foreground);
}

Accessibility

A gauge is one image with nothing to step through, so it takes no tab stop. It's announced by its name, "Gauge: 72%" unless you pass ariaLabel.

Once you name it, the reading moves to ariaDescription, so a screen reader still says the value. Pass your own description to say more, such as the limit.

API reference

Vue takes the same props as React, in camelCase or kebab-case, with class for className. Render props are scoped slots (#content), and callbacks such as onHoverChange can be written as listeners (@hover-change).

Gauge

PropType
orientation?GaugeOrientation

"arc" draws the notches around an arc; "linear" lays them out along a horizontal track.

Default
"arc"
valuenumber

Fill level from 0 to 100: the share of notches drawn in the active colour.

totalNotches?number

Number of notches.

Default
40
spacing?number

Share of the track, in percent, reserved for the gaps between notches.

Default
25
notchCornerRadius?number

Radius in pixels used to round the corners of each notch. 0 keeps them sharp; large values are limited by the notch size and approach a capsule shape.

Default
0
uniformWidth?boolean

true draws notches with parallel sides; false tapers them toward the centre (arc) or midline (linear). Defaults to false for arc gauges and true for linear gauges.

startAngle?number

Angle where the arc starts, in degrees. Arc gauges only.

Default
135
endAngle?number

Angle where the arc ends, in degrees. Arc gauges only.

Default
405
useGradient?boolean

Colour the notches along a gradient instead of one solid colour.

Default
false
activeGradient?readonly [string, string]

[from, to] colours for the active notches, interpolated along the notch index. Used when useGradient is on; defaults to --chart-1 to --chart-5.

inactiveGradient?readonly [string, string]

[from, to] colours for the inactive notches. Used when useGradient is on; defaults to activeGradient.

centerValue?number

Number shown in the label, which is drawn only when this is set. It is independent of value, so it can show a related figure such as revenue.

defaultLabel?string

Caption shown under (arc) or next to (linear) the centerValue.

Default
"Total"
prefix?string

Text shown before the centerValue, for example "$".

suffix?string

Text shown after the centerValue, for example "%".

formatOptions?GaugeStatFormat

Number format for the centerValue, in Intl.NumberFormat terms (notation, currency, fraction digits and so on).

Default
{ maximumFractionDigits: 0, notation: "standard" }
labelPlacement?GaugeLabelPlacement

Where the label sits relative to a linear track. Arc gauges always draw the label in the centre.

Default
"top"
labelAlign?GaugeLabelAlign

Alignment of the label across the linear track: "start", "center" or "end".

Default
"start"
inactiveFill?string

Colour of the inactive notches. Defaults to the --border colour.

activeFill?string

Colour of the active notches. Takes precedence over the gradient options. Defaults to --chart-1.

inactiveFillOpacity?number

Fill opacity of the inactive notches, from 0 to 1.

Default
0.8
activeFillOpacity?number

Fill opacity of the active notches, from 0 to 1.

Default
1
#default?slot

SVG definitions (a pattern tile such as PatternLines) the gauge renders in a hidden <defs>, so activeFill, inactiveFill or a sector's color can paint with url(#id). Their ids are the page's: give each gauge its own.

class?string

Extra class name for the root element.

width?number

Fixed width in pixels. Omit to fill the parent. An arc gauge is fixed-size only when both width and height are set.

height?number

Fixed height in pixels. For a linear gauge this is the track thickness; when omitted the thickness is linearHeight.

minWidth?number

Minimum width in pixels when the gauge fills its parent.

Default
300 for arc gauges, 200 for linear gauges
notchLengthPercent?number

Length of the notches as a percentage of their full length, clamped to 5 to 100.

Default
100
notchWidthPercent?number

Width of each notch as a percentage of its slot, along the track. Linear gauges only.

Default
80
linearHeight?number

Track thickness in pixels when height is not set. Linear gauges only.

Default
24
ruler?boolean | GaugeRulerOptions

Arc only: the scale ticks inside (or outside) the notches, brightening up to the value. true for the defaults, or options.

Type
boolean | GaugeRulerOptions
needle?boolean | GaugeNeedleVariant | GaugeNeedleOptions

Arc only: a pointer that sweeps to the value. true (the gradient needle), a variant name, or options.

Type
boolean | GaugeNeedleVariant | GaugeNeedleOptions
arcStyle?GaugeArcStyle

Arc only: notches, one rounded solid stroke, or none (a sector, ring or dots carry the value).

Default
"notches"
arcThickness?number

Arc only: the solid stroke's thickness as a fraction of the gauge size.

Default
0.035
zones?readonly GaugeZone[]

Arc only: coloured ranges on the 0–100 scale, such as a red zone; later zones win where they overlap.

zoneDisplay?GaugeZoneDisplay

How zones render: a thin band ringing the track, the fill taking the zone colour, or both.

Default
"band"
sector?boolean | GaugeSectorOptions

Arc only: a filled wedge from the start to the value (conic, radial, flat or pattern).

Type
boolean | GaugeSectorOptions
progressRing?boolean | GaugeProgressRingOptions

Arc only: a thin value ring around the track.

Type
boolean | GaugeProgressRingOptions
dots?boolean | GaugeDotsOptions

Arc only: concentric rings of dots that light up to the value.

Type
boolean | GaugeDotsOptions
glow?boolean | GaugeGlowOptions

Arc only: a soft glow on the fill (lit notches, the solid arc, the progress ring).

Type
boolean | GaugeGlowOptions
centerDisc?boolean | GaugeCenterDiscOptions

Arc only: a ringed disc behind the centre label.

Type
boolean | GaugeCenterDiscOptions
enterTransition?GaugeEnterTransition

Transition of the fill's sweep (and of the needle, sector, ring and dots riding it), in the shape used by the motion library (type, duration or visualDuration in seconds, bounce, ease, spring values). Notches light up in order as the sweep passes them; a new value sweeps on from wherever the fill is, keeping its speed.

Default
{ type: "spring", visualDuration: 0.9, bounce: 0 }
enterStaggerScale?number

Scales the delay between the track fading in and the fill starting to sweep (limited to 0.25 to 2.5).

Default
1
geometryScrubbing?boolean

Draw at the value at once, with no fade or sweep (bklit's Studio sets it while a geometry control is scrubbed).

ariaLabel?string

Accessible name of the gauge.

Default
"Gauge: <value>%"
ariaDescription?string

Longer accessible description of the gauge, written as the svg's <desc>. Defaults to the reading ("72%") when ariaLabel is set, so a named gauge still announces its value.

Examples

21 examples on Vue, each live with its code and its own install command.