Gauge Chart
Purpose
A Gauge chart shows a single numeric value positioned within a bounded, meaningful range on a 180-degree semi-circular arc. Use it when the reader needs to answer one question at a glance: where does this value sit within a known range? Common cases include capacity utilisation, percentage of target, and progress against a hard operational limit.
Do NOT use a Gauge when the range is unbounded or arbitrary (e.g., active user counts) — use a KPI tile instead. Do NOT use a Gauge to compare multiple values across categories — use a Bar chart. Do NOT use a Gauge when the trend over time is the primary takeaway — use a Line chart.
Anatomy
A Gauge chart is composed of the following parts:
- Title (required at md and lg density, optional at sm): the headline label placed above the chart. Wraps to a second line before truncating with ellipsis.
- Subtitle (optional): a single context line directly beneath the title. Does not wrap.
- Arc track (required): the full 180-degree background arc from min (left endpoint, 9 o'clock) to max (right endpoint, 3 o'clock), rendered in a muted colour to show the available range.
- Value fill (required): a filled arc drawn clockwise from the min endpoint to the angle that corresponds to the current value. The fill colour is
--force-color-chart-1by default and changes to a status colour when threshold zones are configured. - Centre KPI (required at md and lg): the large numeric value displayed inside the arc bowl, typically rendered as a percentage or raw value on the first line and a short unit label on the second (e.g., "78%" over "of capacity").
- Min label (shown at md and lg): the formatted value at the left arc endpoint.
- Max label (shown at md and lg): the formatted value at the right arc endpoint.
- Threshold ticks (optional): short tick marks on the arc at meaningful threshold boundaries. Required when threshold zones are configured.
- Detail KPIs (optional): an external panel to the right of the arc displaying one or more secondary metrics (e.g., "HEADROOM: 2.2 GB before scale-up trigger"). Controlled by the
headlineMetricprop. - Action menu (optional): a three-dot icon in the top-right corner of the widget, providing Export and Refresh actions.
- Tooltip (optional, default on): anchored above the value position on the arc. Shows the raw value, the percentage of the range, and the zone name when threshold zones are configured.
- Legend (conditional): shown only in the
threshold-zonesvariant. Lists zone names with their colour swatches. Defaults to'none'for all other variants.
The Gauge has no axes. The arc span is always 180 degrees. The arc track always starts at the min value and ends at the max value.
When to Use
Use a Gauge when:
- The value lives within a bounded, meaningful range — 0 to 100%, 0 to a capacity limit, 0 to a hard target.
- The position within the range is the takeaway, not the absolute value alone.
- The reader needs to see "how close to the limit, target, or capacity" at a glance.
- Exactly one value is being shown.
Do NOT use a Gauge when:
- The range is unbounded or arbitrary (e.g., active user count, request count). Use a KPI tile.
- The reader needs to compare multiple values across categories. Use a Bar chart.
- The value changes over time and the trend is the takeaway. Use a Line chart.
- The value has a categorical breakdown. Use a Donut chart.
- The container is narrower than 160px. Use a Progress bar instead.
Data Requirements
| Requirement | Constraint | Behaviour at the limit |
|---|---|---|
| Required fields | value (number), min (number), max (number) |
Missing any field → Empty state with explanation |
| Accepted data types | Numbers only. min must be less than max |
Strings or mixed types are rejected at design time |
| Minimum data points | 1 value | No value → Empty state. Do NOT render a zero-filled arc — a zero fill is visually indistinguishable from an actual zero reading |
| Maximum data points | 1 value plus an optional target |
Additional values are ignored. Multiple series → Error state with redirect to Bar chart |
| Null / missing value | Render the Empty state | Never render a zero-filled arc as a fallback |
| Negative values | Permitted only when min is negative. Values outside [min, max] are clamped |
An out-of-range value triggers the Error state with a banner explaining the clamp |
| Sort order | Not applicable — single value | Caller-provided order is ignored |
| Aggregation | None. Caller provides the value at the desired granularity | Multiple readings in the payload → Error state |
Configuration
Content
| Prop | Type | Default | Purpose |
|---|---|---|---|
title |
string |
required | Headline label above the chart. Wraps to two lines, then truncates with ellipsis. |
subtitle |
string? |
undefined |
Optional single-line context beneath the title. |
headlineMetric |
object? |
undefined |
Optional external KPI panel alongside the gauge. Most cases are served by the centre KPI alone; use this only when a secondary metric (headroom, delta, burn rate) genuinely adds value. |
Data
| Prop | Type | Default | Purpose |
|---|---|---|---|
data |
object |
required | A single object { value, min, max, target? }. Schema defined in Data Requirements above. |
referenceLines |
object[]? |
[] |
Threshold zone definitions for the threshold-zones and target-zone variants. Each zone: `{ from, to, color? |
Visual
| Prop | Type | Default | Purpose |
|---|---|---|---|
variant |
'standard' | 'threshold-zones' | 'with-target' | 'mini' | 'kpi-with-delta' | 'target-zone' |
'standard' |
Approved variants documented in the Variants section. |
colorMapping |
object? |
system | Override the arc fill colour. The threshold-zones variant uses status tokens (success / warning / danger) by default. |
density |
'sm' | 'md' | 'lg' |
'md' |
Controls arc stroke width, label visibility, and KPI size. See the Sizing section. |
theme |
'light' | 'dark' | 'auto' |
'auto' |
Overrides the dashboard-level theme. |
Behavioural
| Prop | Type | Default | Purpose |
|---|---|---|---|
legend |
'bottom' | 'right' | 'none' |
'none' |
Legend is hidden by default. Required when threshold zones are named. |
tooltip |
boolean |
true |
Hover or focus reveals a tooltip at the value position. |
onMarkClick |
function? |
undefined |
Gauges are rarely clickable. Provide only when drill-down is genuinely useful. When set, the gauge becomes focusable and clicking fires the handler with the current reading. |
exportable |
boolean |
true |
Whether the action menu exposes an Export action. |
Variants
standard (default)
A single-colour filled arc from the min endpoint to the value position. The arc track shows the full range in a muted background colour. The centre KPI displays the value. Min and max labels appear at the arc endpoints at md and lg density.
Use when the question is "where on the scale?" and no zone information is relevant.
threshold-zones
The arc is divided into two or more colour bands at meaningful threshold boundaries (for example, Safe: 0–70%, Warning: 70–90%, Critical: 90–100%). The value fill adopts the colour of the zone it lands in. Short tick marks on the arc delineate each zone boundary. A legend lists zone names.
Use when the reader needs to see both the current position and which zone it falls into. The Figma audit recommended this variant for all status-driven readings (capacity, health, SLA compliance) to replace ad-hoc red/green fills.
Status colour assignments: Safe → --force-color-chart-3 (green), Warning → --force-color-chart-4 (orange), Critical → --force-color-chart-5 (cranberry). Zone names and colour labels always appear together — colour alone is never the sole signal.
with-target
The standard arc plus a notch or needle marking the target value position on the arc. The target marker is labelled (e.g., "Target 80"). Use when the question is "are we hitting our target?" rather than "where on the scale?"
A target field must be present in the data prop. If the target is outside [min, max], the chart renders the Error state.
mini
A compact gauge with no centre KPI, no min/max labels, and no arc track labels. Tooltip only. Used inside table cells, status columns, or as a sub-element of a KPI tile where vertical space is at a premium. Always rendered at sm density regardless of the density prop.
kpi-with-delta
A standard arc paired with an external KPI panel showing the current reading, a delta badge (e.g., "+1.6 pp w/w"), and optional secondary metrics such as a burn rate or SLO target. Use when the takeaway is both the current position on the arc and how it has changed.
The external KPI panel is rendered to the right of the arc at md and lg density. At sm density it collapses to a tooltip.
target-zone
A single highlighted band on the arc showing the acceptable range (e.g., 18–24°C). The arc fill outside the band shifts to the warning status colour. A legend entry labels the target zone. Use when the acceptable window is a range rather than a single target value.
States
Default (happy path)
The arc is fully rendered with the value fill drawn clockwise to the current value position. The centre KPI shows the value and unit label. On first render, the fill animates from 0 to the value position over --force-duration-moderate (300ms) using --force-easing-standard. On value update, the fill transitions to the new position over --force-duration-fast (150ms).
Loading
Data is being fetched. Render the arc track at --force-opacity-subtle (0.7) opacity. In place of the centre KPI, render a skeleton block (two lines: a wider primary and a narrower secondary). The title and header remain fully visible. Show a "Loading…" label in the top-right corner. Do NOT show a spinner in the arc bowl — the reduced-opacity track communicates "in progress" without falsely suggesting a zero reading.
Empty
No reading is available (value is null or absent). Render the full arc track without a fill. Show a text message inside the arc bowl explaining why ("No reading available" and a short action hint). Do NOT render a zero-filled arc — this would imply a real reading at the minimum.
Error
Data fetch failed. Render the full arc track without a fill and overlay an error icon, message ("Could not load"), and a Retry button inside the bowl. Never silently fall back to Empty. Use --force-color-icon-destructive for the icon.
No Permission
The viewer cannot see the underlying data. Render the full arc track without a fill and overlay a lock icon and explanation ("You do not have access to this data. Ask an administrator for access."). Do not reveal any value — not even a greyed-out fill.
Partial Data / Stale
The range is known but the current reading is stale (e.g., the monitoring agent has not reported recently). Render the last known value fill at --force-opacity-subtle (0.7) opacity. Add a banner beneath the title stating when the reading was captured ("Last reading captured 12 minutes ago, may be stale"). Label the centre KPI with "(stale)" to prevent misreading.
Interaction
Hover and Focus
On pointer hover or keyboard focus, the arc fill brightens (lightens one step toward the palette midpoint). A tooltip appears anchored 12px above the outer edge of the arc at the value position. On touch, a tap opens the tooltip.
Tooltip
The tooltip is anchored to the value position on the arc (not cursor-following). It shows:
- The raw value with its unit (e.g., "7.8 GB")
- The percentage of range (e.g., "78% of capacity")
- The zone name, when threshold zones are configured (e.g., "Warning zone")
Click
No-op by default. When onMarkClick is provided, the entire gauge becomes focusable and clicking or pressing Enter fires the handler with the current reading. Use only when drill-down is meaningful and the user expects a navigation or filter action.
Legend Interaction (threshold-zones variant)
Clicking a zone name in the legend highlights that band on the arc, dimming all other bands to --force-opacity-subtle. Useful for drawing attention to a specific zone during a presentation. Clicking again removes the highlight.
Zoom and Pan
Not applicable. Gauges are not zoomable or pannable.
Cross-Filter
Not applicable. Gauges are single-value and do not participate in dashboard cross-filter.
Keyboard Navigation
Tabfocuses the gauge widget container.- On focus, the tooltip reveals automatically without further input.
EnterfiresonMarkClickif provided; otherwise no-op.Escapemoves focus to the next widget in the dashboard.- Arrow keys have no effect — there is only one value, nothing to step through.
Accessibility
- Colour contrast: Arc fill, arc track, and centre KPI text all meet WCAG 2.2 AA against the chart background. Status-zone colours (success / warning / danger) resolve to compliant pairs by default.
- Colour-blind safety: Threshold zones use the Force UI status palette supplemented with secondary cues — a tick mark at each zone boundary plus a text label in the tooltip and legend. Colour alone is never the sole signal of zone status.
- Screen reader: The gauge container carries an accessible name derived from
title. A summary string is exposed to assistive technology:"<title>, <value> <unit>, <zone name if applicable>". A data-table fallback is reachable via a keyboard shortcut from within the gauge focus region. - Keyboard reachability:
Tabmoves focus to the gauge. The tooltip reveals on focus. - Focus ring: A visible focus ring using
--force-shadow-focus-ringappears on the gauge container on:focus-visible. Distinct from the hover state. - Reduced motion: When
prefers-reduced-motion: reduceis set, the fill animation on initial render and value update is suppressed. The new value snaps into position immediately. - Text scaling: The component reflows without clipping up to 200% text size. The centre KPI shrinks to the next smaller scale step before truncating. Min/max endpoint labels collapse to tooltip-only when space is insufficient.
Sizing
| Density | Width range | Arc stroke width | What is shown |
|---|---|---|---|
| sm | < 320px | 8px | Arc track and fill only. No centre KPI, no endpoint labels. Tooltip on tap. Effectively the mini variant regardless of variant prop. |
| md | 320–599px | 12px | Centre KPI value and unit. Min/max labels at arc endpoints. Threshold zone tick marks (no named legend). |
| lg | ≥ 600px | 16px | Centre KPI with value, unit, and percentage. Min/max labels with units. Threshold zone tick marks with a named legend when variant: 'threshold-zones'. |
At all densities, the arc aspect ratio is fixed: the plot area is square and the arc occupies the upper half, so the component height equals approximately 60% of its width (half-circle plus endpoint labels and padding).
Below 160px wide, drop the gauge entirely and substitute a Progress bar component.
Guidance
Do
- Always supply a bounded, meaningful
minandmax. The arc position is only informative when the range has a real-world interpretation (0–100% capacity, 0 to allocated GB). A gauge with an invented range misleads the reader. - Use threshold zones for any status-driven reading (capacity, health, SLA). The zones turn the arc into a "where am I relative to the danger zone?" answer, which is more useful than a single colour.
- Always pair status colours with text labels. A red fill with no caption tells the reader something is wrong but not what or why. Use the
threshold-zonesvariant and name each zone. - Use one canonical gauge style (semi-circular) throughout the product. Do not mix semi-circular gauges, radial gauges, and traffic lights in the same dashboard — the reader learns the grammar once and applies it everywhere.
Don't
- Do NOT use a gauge for unbounded values (active user counts, total requests, cumulative bytes transferred). The arc position becomes meaningless when the upper bound is arbitrary. Use a KPI tile.
- Do NOT render a zero-filled arc for missing or null data. A zero fill implies a real reading at the minimum. Show the Empty state instead.
- Do NOT place multiple gauges for the same metric when a single gauge at a wider width would suffice. Gauge grids work for comparing the same metric across peers (e.g., disk capacity across hosts), but not for comparing unrelated metrics — use a bar chart for that.
- Do NOT use the
minivariant as the only representation of a critical metric. The mini gauge has no labels and no KPI; it is a supporting visual element, not a primary answer surface.
Token Usage
Arc track
- Fill:
--force-color-bg-muted(neutral.100) - Stroke: none
Arc fill — standard variant
- Fill:
--force-color-chart-1(indigo.500) - Hover brighten:
--force-color-chart-1at--force-opacity-subtleoverlay on the fill (implementation-level effect)
Arc fill — threshold-zones variant
- Safe zone fill:
--force-color-chart-3(green.500) - Warning zone fill:
--force-color-chart-4(orange.500) - Critical / danger zone fill:
--force-color-chart-5(cranberry.500) - Tick marks at zone boundaries:
--force-color-bg-surface(white), 2px wide, full arc stroke height
Target marker (with-target variant)
- Notch fill:
--force-color-text-primary - Notch width: 3px, full arc stroke height
- Target label:
--force-font-size-xs,--force-color-text-secondary
Target zone highlight (target-zone variant)
- Highlighted band fill:
--force-color-chart-6(blue.500) at 40% opacity over the track - Segment outside the target zone:
--force-color-chart-4(orange.500) fill - Zone label:
--force-font-size-xs,--force-color-text-secondary
Centre KPI
- Primary value text:
--force-font-size-3xl(lg),--force-font-size-2xl(md) — font weight--force-font-weight-semibold - Unit label:
--force-font-size-sm,--force-font-weight-regular,--force-color-text-secondary - Loading skeleton:
--force-color-bg-muted, animated shimmer
Status badge (threshold-zones tooltip and legend)
- Background: matches zone fill (success / warning / danger status token)
- Text:
--force-color-text-on-primary - Border radius:
--force-radius-badge
Min / max labels
- Text:
--force-font-size-xs,--force-color-text-secondary - Alignment: left-aligned (min) and right-aligned (max) below the arc endpoints
Title and subtitle
- Title:
--force-font-size-md,--force-font-weight-medium,--force-color-text-primary - Subtitle:
--force-font-size-sm,--force-font-weight-regular,--force-color-text-secondary
Tooltip
- Background:
--force-color-bg-surface-overlay - Border:
--force-color-border-default - Shadow:
--force-shadow-md - Text:
--force-font-size-sm,--force-color-text-primary - Secondary rows:
--force-color-text-secondary
Stale / partial data
- Arc fill opacity:
--force-opacity-subtle(0.7) - Banner background:
--force-color-bg-warning-subtle - Banner text:
--force-color-text-warning,--force-font-size-xs
Focus ring
- Box shadow:
--force-shadow-focus-ring - Applied via
:focus-visibleon the gauge container
Animation
- Initial fill:
--force-duration-moderate(300ms),--force-easing-standard - Value update:
--force-duration-fast(150ms),--force-easing-standard - Suppressed when
prefers-reduced-motion: reduce
Related Components
| Component | Relationship | When to redirect |
|---|---|---|
| KPI tile | Single-value alternative | When the value has no bounded range, or when the absolute number is the takeaway rather than its position in a range |
| Progress bar | Inline linear alternative | When the container is too narrow for a usable gauge (below 160px), or when a compact inline indicator is sufficient |
| Donut chart (goal-progress variant) | Alternative progress metaphor | When the visual brief is "filling toward a goal" rather than "where on a known scale" |
| Bar chart | Multi-value alternative | When the same metric must be compared across multiple categories or peers |
| Line chart | Time-series alternative | When the trend over time is the takeaway rather than the current position |