Skip to content
KONIGI Patterns

Dashboards / Key measures / Target and progress

‹ 7 of 7

Target and progress

People need to see how far they are from a goal and whether they are on pace.

Updated September 9, 2026

Problem

A current value alone does not show the distance to a goal or whether progress is on pace.

Solution

Show the measured value against a clearly labeled target. A compact bar with a target marker can also include background ranges when those ranges have defined meanings.

Use readable labels and distinguish ranges by more than red and green alone. Show expected progress by now when the goal has a deadline.

Allow the scale to show values beyond the target when exceeding it is possible. Keep the target’s definition and review information available.

Use when

There is an agreed goal and people can act on the gap or pace toward it.

Don’t use when

The “target” is decorative. A progress bar against a number nobody committed to is a bar chart with extra implication, and it teaches viewers to ignore the ones that matter. Also don’t use it when the metric has no meaningful ceiling; progress toward infinity is just a value.

Trade-offs

A progress bar can hide how quickly the value is changing. Old targets may become irrelevant, and visible goals can encourage optimizing the metric at the expense of the real outcome. A full bar should not imply a maximum unless one exists.

Checklist

  • Who set this target, when, and is it still the right one?
  • Is expected progress by now shown, or only progress to date?
  • What happens visually past 100%, and is overshooting good here?
  • Are the qualitative bands encoded as intensities of one hue rather than red/amber/green?
  • Would a colorblind reader get the same reading as everyone else?
  • Is the target a line the eye can locate precisely, or a color boundary it has to estimate?
  • Does the bar start at zero, and if the range doesn’t, is that labelled?
  • Is the underlying number visible, or only the proportion?
  • If this is a budget being consumed, does the display show burn rate as well as balance?
  • What does it show before the period starts, and after it ends?

Compare

Grafana’s bar gauge is the closest thing in the category and stops short of a bullet graph: thresholds color the bar itself rather than sitting behind it as ranges, so the qualitative context and the measure share one channel instead of two. Honeycomb frames the same pattern as error budget rather than progress, showing what’s left and how fast it’s going, which answers the pace question the generic progress bar drops. Tableau ships Few’s bullet graph as a built-in, which is why it’s the version most analysts have actually seen. Netdata largely skips targets, on the position that a per-second chart with a threshold line already says everything a progress bar would.

Gauge is a radial alternative for a bounded range. KPI tile emphasizes the value. Metric targets defines and maintains the goal.

Threshold line places the reference on a time chart. Semantic status color supplies consistent state cues.

Target and progress anatomy A bullet graph broken into four numbered parts: label, qualitative ranges as three intensities of one hue, the featured measure as a bar, and the target as a perpendicular marker crossing it. Below, two bars both sixty percent full, one in week eleven of the quarter and one in week fifty. Anatomy · Few's bullet graph Q3 revenue US$ thousands 1 0 250 500 750 1,000 2 3 4 1 LABEL AND UNITS Outside the graphic, so the bar stays a bar. 2 QUALITATIVE RANGES Poor, satisfactory, good as three intensities of one hue. Red, amber and green become three identical greys for a colourblind reader. 3 FEATURED MEASURE One bar, flat fill, no gradient. It is the only thing in the graphic the eye should land on. 4 TARGET A marker crossing the bar, not a number printed somewhere else on the page. Sixty percent of quota, two different weeks Both bars are sixty percent full. The mark is where each should be by now. Quota attainment Week 11 of 52 Quota attainment Week 50 of 52
Wireframe — the pattern's anatomy, not any one product's version of it

Implementation

shadcn's Progress is a percentage of itself. A dashboard target needs three numbers: where you are, where you should be by now, and where you finish. A bar that only knows the first is the one that reports green all quarter.

shadcn
npx shadcn@latest add progress
Tokens
--background--foreground--muted--muted-foreground--border--status-critical--status-nominal--chart-1
Q3 revenueUS$ thousands720 / 1,000

Pace says 63% by now—ahead

Progress.tsxCarries a pace marker, so ahead and behind are visible rather than inferred.

/**
 * Progress against a target needs the pace marker, not just the fill.
 *
 * 62% of the way to a number is good news in week eleven and bad news in week
 * two, and a bar showing only the fill cannot tell you which. `expected` is the
 * position you should have reached by now, drawn as a tick, so ahead and behind
 * are read rather than calculated.
 */
export function Progress({
  value,
  target,
  expected,
  label,
  unit,
}: {
  value: number;
  target: number;
  /** Outside the graphic, so the bar stays a bar. */
  unit?: string;
  /** Where pace says you should be. Required—the bar is misleading without it. */
  expected: number;
  label: string;
}) {
  const pct = Math.min(100, (value / target) * 100);
  const pacePct = Math.min(100, (expected / target) * 100);
  const behind = value < expected;

  return (
    <div>
      <div className="flex items-baseline justify-between gap-3 text-sm">
        <span className="text-foreground">{label}{unit && <span className="ml-2 text-xs text-muted-foreground">{unit}</span>}</span>
        <span className="tabular-nums text-muted-foreground">
          {value.toLocaleString()} / {target.toLocaleString()}
        </span>
      </div>
      <div className="relative mt-2 h-2 w-full overflow-hidden rounded-full bg-muted">
        <div
          className="h-full rounded-full"
          style={{ width: `${pct}%`, background: behind ? "hsl(var(--status-warn))" : "hsl(var(--status-nominal))" }}
        />
        {/* The tick sits on top, because pace is a fact about the bar rather
            than a second quantity competing with it. */}
        <span
          className="absolute top-[-2px] h-[calc(100%+4px)] w-px bg-foreground"
          style={{ left: `${pacePct}%` }}
          aria-hidden="true"
        />
      </div>
      <p className="mt-1 text-xs text-muted-foreground">
        Pace says {Math.round(pacePct)}% by now—{behind ? "behind" : "ahead"}
      </p>
    </div>
  );
}

demo.tsxHow it is called: value, target, and where pace says it should be.

import { Progress } from "./Progress";

/** Progress against a target, with the pace tick saying where it should be by now. */
export default function Demo() {
  return (
    <div className="w-[480px] max-w-full">
      <Progress label="Q3 revenue" unit="US$ thousands" value={720} target={1000} expected={625} />
    </div>
  );
}
What it renders. Identical markup in both panes, with only the token values changing.

Examples

Screenshots are grouped by product and include the capture date. Dashed boxes highlight this pattern. Notes appear below each screenshot and when you hover over a box.

Tableau Public

Published workbooks show how individual authors arrange charts and interactions in Tableau.

Emergency Department / Clinical Dashboard September 11, 2026 Tableau Public embed view; emergency department patient flow workbook dense · light · desktop-web
This workbook analyzes emergency-department activity rather than showing a live bed board. Its hour-by-weekday grid makes recurring busy periods easy to locate. Monthly small multiples support seasonal comparison on a shared scale. The color ramps need careful labeling: a diverging scale on a count or duration needs a meaningful center, not an unexplained midpoint.
Show 1 more example Hide the rest

Grafana

Examples of panel grids, shared selectors, stat tiles, and chart configuration.

Grafana SLO / SLO Overview September 10, 2026 Grafana Play (signed out; no version string exposed) dense · dark · desktop-web
The overview lists twenty-eight objectives with an indicator, remaining budget, and sparkline for each. The budget column combines large negative percentages with positive values, but gives little explanation of how to read them. No data uses the same red as breached objectives, making missing information harder to distinguish from a failed target. The sparklines also use different scales, so their shapes cannot be compared directly across rows.
  • Metric targets The budget column adds context to each objective’s result.
  • Target and progress Large negative budget values need a clear explanation of the calculation.
  • Error and stale state No data uses the same red treatment as a breach.
  • Small multiples Sparkline scales differ between rows, limiting direct comparison.
  • Header KPI strip The top tiles count targets, objectives, and series rather than showing whether goals are met.