GaugeChart

A single bounded value on a dial — an arc over a restricted sweep, with the exact number in the middle. Good for a status summary; a `Progress` bar is the better read when the value needs comparing to another one.

vue
<UiGaugeChart :modelValue="..." :ariaLabel="..." />

Needs the charts module

This component ships in @jgastager/bundy-ui/charts, a separate module so projects that never draw a chart don't carry the paint classes these need. Nothing extra to install — just add the module entry. See Charts.


Options

One block per prop — what it does, and what it looks like set.

Model value

required

modelValue is the reading. It's clamped into min…max before it's drawn, so an out-of-range value pins the arc rather than overshooting it. An array breaks one reading into the parts that make it up — the arc still ends at the total, with the split visible inside it.

72%of quota
72%of quota
  • Documents
  • Media
  • Backups

An array is a breakdown of one reading, not several readings: the entries are lengths stacked from min, so the arc still reports a single total and the readout is what they add up to. Several independent values want separate gauges, or a RadialBarChart.

The hover fade is a CSS transition over the library's own 250ms duration, so it costs nothing and honours prefers-reduced-motion. There's no animate prop and nothing tweens on a data change — the marks are plain SVG elements Vue patches directly.

ARIA label

required

ariaLabel is required. A gauge is a single number drawn as an angle — this is what makes that number available at all without sight.

72%of quota

ARIA description

ariaDescription is the detail the label shouldn't carry — a threshold, a trend, what happens at the top of the range.

Uploads are blocked once usage passes 90%.72%of quota

Min

min is the bottom of the range. Raise it when zero isn't a meaningful floor — a temperature, a score that starts at 200 — so the arc spends its length on the part that varies.

680credit score

model-value is clamped into min…max before drawing, so an out-of-range value shows a full or empty dial rather than an arc that wraps around.

Max

max is the top of the range, and what the percentage readout is a percentage of. Set it to the real ceiling rather than the largest value you happen to have.

8,400requests / hr

Label

label is the text under the readout, naming what's being measured. Without it the gauge is a number with no subject.

72%
72%of quota

Labels

labels names a breakdown's segments, in the same order as the values. Without them the parts are unexplained colors: the middle of the gauge belongs to the total, so the legend is the only place their names can go.

72%of quota
72%of quota
  • Documents
  • Media
  • Backups

Display

display replaces the center readout wholesale. Reach for it when the number to show isn't a function of the value — a grade, a status word, a fraction.

Bservice health

Value format

valueFormat formats the center readout, which otherwise shows the percentage of the range. It formats each segment's value in the legend too, so a breakdown's parts read in the same units as its total.

8,400requests / hr

Sweep

sweep sets how far around the circle the track runs, centred on twelve o'clock. 270 is the classic dial; 180 is the half-circle that sits under a stat tile without wasting the height a full dial needs.

72%180°
72%270°
72%340°

sweep="180" is a half-circle that stacks tightly in a row of stat tiles; the default 270° is the classic dial.

Thickness

thickness is the arc's width as a fraction of the radius. Thin reads as precise, thick as a status light — pick from how the number is meant to be used, not from how much room there is.

72%
72%
72%

Gap

gap separates a breakdown's segments, in degrees. It's taken out of the joins only — the two ends of the run are where the reading is, so a gap there would change the number the arc reports.

72%0°
72%2°
72%6°

Color

color paints the filled arc — and the first segment of a breakdown, so it keeps doing the obvious thing when a single reading later grows a split. Binding it to a threshold is the usual move: the gauge then changes meaning as the value crosses one, without any extra chrome.

34%healthy
72%filling up
94%critical

Colors are the library's own semantic ones — primary, secondary, success, warning, error, info, pending, neutral — and any shade of them, primary-400 through primary-950, exactly as the bg-* utilities spell them. Set color per series (or per item) to pin one; leave it unset to take the next slot of the default sequence. neutral and secondary are never handed out automatically, so an unlabelled series never lands on them.

Colors

colors paints a breakdown's segments, positionally. Left unset they take the library's default sequence, which is ordered so neighbouring pairs stay apart for a colorblind reader — set it when the parts carry meanings of their own, like an Other bucket that should recede.

72%of quota
  • Documents
  • Media
  • Backups
72%of quota
  • Documents
  • Media
  • Backups

Track color

trackColor paints the unfilled remainder. Lighten it on a raised surface so the track doesn't read as a hole punched through the card.

72%default track
72%lighter track

Tooltip

tooltip names what's under the pointer on hover. On a breakdown that's the segment, identified without tracing its color back to the legend; on a single reading it's the value the other way round from the readout — the percentage of the range beside the number in its own units. Only the filled arc answers: the track past the reading is the remainder, not a datum.

72 GBof quota
  • Documents · 38 GB
  • Media · 22 GB
  • Backups · 12 GB
72 GBof quota
  • Documents · 38 GB
  • Media · 22 GB
  • Backups · 12 GB

Only the filled arc is hoverable. The track past the reading is the remainder rather than a datum, so a pointer over it closes the panel instead of holding the last segment's open — and the middle belongs to the readout, not to the arc. Hovering a breakdown also dims the segments that aren't under the pointer.

Animate

animate is on by default: the arc sweeps up from min on the first draw and eases to each new reading. Roll new values to compare it with the chart on the right, which has it off. Only the arc moves — the readout always shows the real number — and a reader who has asked their system for reduced motion gets no motion either way.

64%of quota
64%of quota

Legend

legend lists a breakdown's segments under the gauge. It needs labels — there's nothing to name without them — and never appears on a single reading, whose readout and label already say what it is.

72%of quota
72%of quota
  • Documents
  • Media
  • Backups

Legend position

legendPosition puts the legend above the gauge instead of below it. Above works when the gauge sits at the bottom of a tile and the names are what the eye should meet first.

  • Documents
  • Media
  • Backups
72%
72%
  • Documents
  • Media
  • Backups

Legend align

legendAlign places the entries across the legend's width. Centred by default, since the gauge it belongs to is centred too.

72%
  • Documents
  • Media
  • Backups
72%
  • Documents
  • Media
  • Backups
72%
  • Documents
  • Media
  • Backups

Legend orientation

legendOrientation stacks the entries one per line. Worth it once the labels are long enough to wrap, or when valueFormat prints a value beside each one.

72%
  • Documents
  • Media
  • Backups
72 GB
  • Documents · 38 GB
  • Media · 22 GB
  • Backups · 12 GB

Legend group

legendGroup names a group that a standalone UiChartLegend with the same group belongs to, so the legend can sit anywhere — here above the plot — and still dim the other segments while you hover an entry. The chart hands the legend its entries, colors included, so it needs no items. Switch the chart's own legend off if you don't want two.

72%

Height

height is the plot's height in pixels; the arc is sized to fit inside it. It's ignored once aspectRatio is set.

72%
72%

Aspect ratio

aspectRatio sizes the gauge from its container's width instead of a fixed height.

72%of quota

Loading

loading is a skeleton at the gauge's exact height, so a tile doesn't resize when the reading lands.


Examples

The component in real use: compositions that answer "how do I build X with this", rather than one prop at a time.

When a Progress is the better read

A gauge spends a lot of space on one number. If the value is a straightforward completion — a form, an upload, a quota bar in a settings row — a Progress says the same thing in a line.

Storage72%

The readout in the middle isn't decoration — arc length gives a rough read at best, so the exact number is what the viewer actually takes away.

Good at "roughly where in the range am I", poor at comparison: two dials side by side are much harder to rank than two bars. If the value needs comparing to another one, use Progress.


API Reference

Generated from the component's source — props, slots and emits as the component actually declares them.

Props

Prop
Type
Default
Description
modelValuerequired
number | number[]
—
The value to show. Clamped into `min`…`max` before it's drawn. An array is a breakdown of one reading rather than several readings: each entry is a length along the range, laid end to end from `min`, so the arc still ends at a single position — the total — with the parts that make it up visible inside it. Several *independent* values want separate gauges, or a `UiRadialBarChart`.
ariaLabelrequired
string
—
What the gauge shows, for screen readers. Required.
string
—
A longer accessible description, for detail the label shouldn't carry.
number
0
Bottom of the range, and where a breakdown's first segment starts.
number
100
Top of the range.
string
—
Text under the readout, naming what's being measured.
string[]
—
Names for a breakdown's segments, positionally matched to `modelValue`. Carried by the legend.
string
—
Replaces the center readout. Defaults to the percentage of the range.
(value: number) => string
—
Formats the center readout, and each segment's value in the legend.
number
270
How far around the circle the track runs, in degrees, centred on twelve o'clock. `270` is the classic dial; `180` is a half-circle that stacks tightly in a row of stat tiles.
number
0.28
Thickness of the arc as a fraction of the radius.
number
2
Gap at the joins, in degrees — between a breakdown's segments, and between the reading and the track that carries on past it. Taken out of the joins only: the two ends of the run are where the reading is, so shortening them would change the number the arc reports.
ChartColorName
'primary'
Paint for the filled arc, and for the first segment of a breakdown.
ChartColorName[]
—
Per-segment colors, positionally matched to `modelValue`. Defaults to the standard sequence.
ChartColorName
'neutral-800'
Paint for the unfilled remainder, past where the reading stops.
boolean
true
Shows a panel on hover naming what's under the pointer. It reports the reading the other way round from the readout in the middle — the percentage of the range beside the value in its own units — so the two aren't the same number twice. On a breakdown it's how a segment is identified without tracing its color back to the legend.
boolean
true
Sweeps the arc up from `min` on the first draw, and eases it to each new reading. The readout always shows the real number. Readers who ask their system for reduced motion get no animation either way.
boolean
true
Shows the legend naming a breakdown's segments. Needs `labels` — there's nothing to list without it.
"top" | "bottom"
'bottom'
Where the legend sits relative to the gauge.
"start" | "center" | "end"
'center'
Horizontal placement of the legend.
"horizontal" | "vertical"
'horizontal'
How the legend entries flow.
string
—
Names the group a `<UiChartLegend group="…">` elsewhere on the page belongs to, so hovering its entries dims this chart's other marks. Set it — usually with `:legend="false"` — to place the legend anywhere you like instead of under the plot.
number
220
Height of the plot in pixels. Ignored when `aspectRatio` is set.
number
—
Width-to-height ratio, sizing the chart from its container's width.
boolean
false
Replaces the plot with a skeleton of the same height.

Types

ts
interface ChartPlot {
    x: number;
    y: number;
    width: number;
    height: number;
    /** Right edge, since marks need it more often than the width. */
    right: number;
    /** Bottom edge, which is also the x axis' baseline. */
    bottom: number;
}
ts
type ChartColorName = ChartColorFamily | `${ChartColorFamily}-${ChartColorShade}` | `[${string}]`;