# Gauge

> A React gauge chart showing one value against a scale and its zones: a speedometer arc, needle or segmented dial with a target tick.

- Type: React chart component (Charts & Stats)
- Access: Pro (the source needs a Wingo UI Pro plan, see https://wingo-ui.com/pricing)
- Version: 1.0.0
- Install: `npx wingo-ui@latest add gauge`
- Docs: https://wingo-ui.com/components/gauge

## Interaction

A read-only meter, not focusable: nothing to tap or hover. The first time it scrolls into view the arc sweeps from the minimum on a soft spring (the needle turns, the segment marker rides the track) while the number counts up; later values glide from where they were, and the arc changes color as the value crosses into another zone. A long label or description that would not fit the bowl moves under the dial. Screen readers hear it as a meter with the formatted value, the zone and the target ("67.6%, Close zone, target 75%"). Drag the playground's slider to move the value. Reduced motion shows the final state at once.

## Installation

```bash
npx wingo-ui@latest add gauge
```

Pro item: run `npx wingo-ui@latest login` once with a Pro account. The CLI adds the files, their dependencies and a version record for updates.

With shadcn: `npx shadcn@latest add @wingo-ui/gauge` (needs the @wingo-ui registry with your API key in components.json)

Files:

- `components/ui/gauge.tsx`

npm dependencies: `npm i motion d3-shape && npm i -D @types/d3-shape`

Wingo UI dependencies (installed automatically):

- [Chart kit](https://wingo-ui.com/components/chart-kit) ([Markdown](https://wingo-ui.com/components/chart-kit.md))
- [Motion presets](https://wingo-ui.com/components/motion) ([Markdown](https://wingo-ui.com/components/motion.md))
- [Number format](https://wingo-ui.com/components/number-format) ([Markdown](https://wingo-ui.com/components/number-format.md))
- [Tones](https://wingo-ui.com/components/tones) ([Markdown](https://wingo-ui.com/components/tones.md))
- [UIProvider](https://wingo-ui.com/components/ui-config) ([Markdown](https://wingo-ui.com/components/ui-config.md))
- [useLocale](https://wingo-ui.com/components/use-locale) ([Markdown](https://wingo-ui.com/components/use-locale.md))

## Usage

```tsx
import { Gauge } from "@/components/ui/gauge"

export function SalesGoal() {
  return (
    <Gauge
      value={67.6}
      valueFormat="percent"
      target={75}
      thresholds={[
        { value: 0, tone: "danger", label: "Behind" },
        { value: 50, tone: "warning", label: "Close" },
        { value: 75, tone: "success", label: "Good" },
      ]}
      label="Monthly sales goal"
      description="$6,760 of $10,000"
      locale="en-US"
    />
  )
}
```

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `value` | `number \| null` | `67.6` | The current value. Outside min..max it is clamped for drawing, the text still shows the real number. null draws the track only and a dash. |
| `min?` | `number` | `0` | Start of the scale. min >= max renders the empty state (with a warning in development). |
| `max?` | `number` | `100` | End of the scale. |
| `variant?` | `"arc" \| "needle" \| "segments"` | `"arc"` | arc fills the track up to the value; needle is a thin zone-colored track with a needle; segments cuts the track into zones (the current one solid, the rest at 25%, a ring marker at the value) or, with a segments count, into equal steps that light up. |
| `sweep?` | `180 \| 240 \| 270` | `"240"` | Degrees of the dial, symmetric around 12 o'clock. 180 is a half circle, 270 an open ring. |
| `size?` | `"sm" \| "md" \| "lg"` | `"md"` | Width 120 / 200 / 280px (the dial shrinks with a narrower container) and the value 18 / 28 / 40px. |
| `thickness?` | `number` | `0` | Track width in px. Auto is 10% of the width (12 / 20 / 28px), 4px for the needle track. |
| `tone?` | `"neutral" \| "brand" \| "success" \| "warning" \| "danger" \| "info"` | `"neutral"` | The arc color when no zone applies (no thresholds, colorByZone off, or a value below the first zone). neutral is the foreground ink. |
| `color?` | `string` | `""` | Any css color, a palette slot ("series-3") or a tone name. Replaces the tone; zones still win while colorByZone is on. |
| `thresholds?` | `{ value: number; tone: Tone; label?: string }[]` |  | Zone starts, in any order (they are sorted): each zone runs from its value to the next one or max. Labels name the zone in the chip and the spoken text. Lower is better? List them success, warning, danger. |
| `colorByZone?` | `boolean` | `true` | The arc and the chip take the tone of the zone the value is in. |
| `showBands?` | `boolean` | `true` | A thin 3px zone band outside the arc (arc variant with thresholds); the zones the value is not in fade back. |
| `segments?` | `number` | `0` | Equal steps for the segments variant that light up to the value (tinted by their zone when there are thresholds). Auto is one segment per zone, or 10 steps without thresholds. |
| `target?` | `number` | `0` | A tick across the track, cut into the surface so it reads over any color, and part of the spoken text. Hidden outside min..max. No default: without it there is no tick (the playground's 0 places it at 75 % of the range). |
| `roundCaps?` | `boolean` | `true` | Rounded arc ends (segment corners get a 4px radius). Off gives square ends. |
| `label?` | `ReactNode` | `""` | Under the value, e.g. "Monthly goal". A string also names the meter; other nodes label it through aria-labelledby. |
| `description?` | `ReactNode` | `""` | Under the label in muted text, e.g. "$6,760 of $10,000". Linked with aria-describedby. |
| `showValue?` | `boolean` | `true` | The big number in the bowl. |
| `showMinMax?` | `boolean` | `true` | The scale ends under the arc ends, compact for big numbers ("$190K"). |
| `showZone?` | `boolean` | `true` | A small chip in the zone's tone with its label, when the current zone has one. |
| `valueFormat?` | `ChartValueFormat ("number" \| "compact" \| "currency" \| "percent")` | `"number"` | How the value and the scale ends print. percent takes whole numbers: 67.6 is "67,6 %". |
| `currency?` | `string` | `"USD"` | ISO 4217 code for valueFormat="currency", with its narrow symbol ("$", "€"). |
| `decimals?` | `number` | `0` | Fraction digits of the value. Unset (Auto in the playground) keeps the final value's digits all through the count (67.6 counts in tenths, 42 in whole numbers). |
| `formatValue?` | `(value: number, context: { kind: "value" \| "tick" \| "label" }) => string` |  | Full control over the text, e.g. v => `${v.toLocaleString("en-US")} h`. value is called on every frame of the count, tick for min / max, label for the spoken text. |
| `locale?` | `string` | `""` | Intl locale for every number. Empty follows the UIProvider, then the page. |
| `surface?` | `string` | `""` | The color behind the gauge: the target notch and the segment marker are cut in it. Empty uses the surface token. |
| `animated?` | `boolean` | `true` | Sweeps and counts in the first time it scrolls into view, then glides between values. Off renders the final state (thumbnails, print). |
| `loading?` | `boolean` | `false` | The chart kit's gauge skeleton and a placeholder for the value; the label stays. |
| `labels?` | `{ target?: string; zone?: (label: string) => string; valueText?: (value, min, max, info) => string; empty?: string; loading?: string }` |  | The spoken text. Defaults: "target", "{label} zone", "No data", "Loading"; valueText replaces the whole aria-valuetext (info has the formatted text, zone and target). |
| `classNames?` | `Partial<Record<"dial" \| "svg" \| "track" \| "band" \| "arc" \| "segment" \| "needle" \| "marker" \| "target" \| "content" \| "value" \| "label" \| "description" \| "zone" \| "min" \| "max", string>>` |  | Extra classes for the parts. |
| `className?` | `string` |  | Extra classes for the root, merged last. |

## Parts

### DEFAULT_GAUGE_LABELS (constant)

The English strings: "target" and the zone suffix in the spoken text, plus "No data" and "Loading"; valueText is left to the built-in sentence.

## Examples

- **NPS needle**: min -100, max 100, four labelled zones and a needle that settles on 42.
- **Segments, lower is better**: Support response time: zones run success, warning, danger; a marker at 3.2 h and a 4 h target.
- **Live updates**: Each paid invoice glides the arc forward; past 75 % it turns green.
- **Sweeps**: 180, 240 and 270 degrees with the same value, zones and target.
- **Sizes in KPI cards**: sm in list rows, md and lg in cards, currency with compact scale ends.
- **Neutral, brand and custom color**: The monochrome default, brand orange with square ends, a palette slot on segments.
- **Loading and no data**: The kit's gauge skeleton, and a null value that draws the track and a dash.

## See also

- [Radial bar](https://wingo-ui.com/components/radial-bar) ([Markdown](https://wingo-ui.com/components/radial-bar.md))
- [Progress](https://wingo-ui.com/components/progress) ([Markdown](https://wingo-ui.com/components/progress.md))
- [Stat Card](https://wingo-ui.com/components/stat-card) ([Markdown](https://wingo-ui.com/components/stat-card.md))
- [Chart kit](https://wingo-ui.com/components/chart-kit) ([Markdown](https://wingo-ui.com/components/chart-kit.md))
- [Slider](https://wingo-ui.com/components/slider) ([Markdown](https://wingo-ui.com/components/slider.md))
- [Animated Counter](https://wingo-ui.com/components/animated-counter) ([Markdown](https://wingo-ui.com/components/animated-counter.md))

---

Canonical: https://wingo-ui.com/components/gauge
More components: https://wingo-ui.com/components · Index for agents: https://wingo-ui.com/llms.txt
