Components

Status legend

A wrap-friendly grid of colored-dot + label + value columns used above status-distribution charts (Succeeded / Declined / Refunded / Error / Pending / Created) and dual-axis charts (Payments primary + Conversion rate secondary). Each item stacks [dot + label muted] then [value foreground medium]. Purely display — no interactivity. Use ProviderLegendRow when you need click-to-filter behavior.

Updated Sep 24, 2026 by Juan Pablo Turina

Anatomy

A flex-wrap container that lays out N columns with gap-x-8 gap-y-3. Each column has two rows: first row = dot + text-xs muted label; second row = text-base font-medium foreground value. Wraps automatically at container width.

Succeeded
13,880,000
Declined
7,751,000
Refunded
258,628
Error
20,338
Pending
337
Created
93
  1. 1
    Container

    flex flex-wrap items-start gap-x-8 gap-y-3. Wraps to as many rows as the container width allows.

  2. 2
    Dot

    Color from item.color. The six-status recipe mirrors production's colours; see its note.

  3. 3
    Label

    text-xs text-muted-foreground. Series name (e.g. 'Succeeded').

  4. 4
    Value

    text-base font-medium text-foreground. Pass a formatted string (tabular-nums recommended for cross-column comparability).

Recipes

Six-series (Volume status distribution)Production mirror

Production mirror: the Insights status distribution as it ships today, with production's colours. Use it only to rebuild that card. In a new flow each state keeps its StatusBadge colour, icon and word (Created --status-info, Pending warning, Succeeded success, Declined and Error destructive, Refunded --status-refunded): see the Payment states recipe on /components/chart. The canonical Insights shape: 6 payment statuses (Succeeded / Declined / Refunded / Error / Pending / Created) rendered with their current volume. Wraps naturally on narrow cards.

Succeeded
13,880,000
Declined
7,751,000
Refunded
258,628
Error
20,338
Pending
337
Created
93
<StatusLegend items={[
  { key: "succeeded", label: "Succeeded", color: "var(--chart-6)",  value: "13,880,000" },
  { key: "declined",  label: "Declined",  color: "var(--chart-5)",  value: "7,751,000"  },
  { key: "refunded",  label: "Refunded",  color: "var(--chart-3)",  value: "258,628"    },
  { key: "error",     label: "Error",     color: "var(--chart-4)",  value: "20,338"     },
  { key: "pending",   label: "Pending",   color: "var(--chart-17)", value: "337"        },
  { key: "created",   label: "Created",   color: "var(--chart-7)",  value: "93"         },
]} />
Dual (Payments + Conversion rate)Production mirror

Production mirror: the legend of the payments and conversion rate card as it ships today, two scales in one plot. Use it only to rebuild that card. In a new flow, the rate sits on its declared band (the Rate and volume recipe on /components/chart), not on 0 to 100. The composed dual-axis card legend: two columns naming the two series (primary bar + secondary line) with their current values above the chart body.

Payments
2,283,428
Conversion rate
60.12%
<StatusLegend items={[
  { key: "payments",   label: "Payments",        color: "var(--primary)", value: "2,283,428" },
  { key: "conversion", label: "Conversion rate", color: "var(--chart-1)", value: "60.12%"    },
]} />

Import

Copy this import line at the top of the file where you compose this atom.

StatusLegend is a pure display atom — no state, no callbacks. Compose it as the first child of a ChartCard body, above the chart itself.
import { StatusLegend, type StatusLegendItem } from "@/components/ui/status-legend";

Props

Everything else from the underlying HTML or Radix primitive is forwarded via ...props.

StatusLegend

PropTypeDefaultDescription
itemsStatusLegendItem[] (required)—The columns to render. See below.
classNamestring—Extra classes on the outer flex-wrap container.

StatusLegendItem

PropTypeDefaultDescription
keystring (required)—Stable key used for React reconciliation.
labelstring (required)—Series label. text-xs, muted.
colorstring (required)—Dot color. A new flow: var(--series-N) for entities, the StatusBadge colours for payment states. The six-status recipe keeps production's --chart-* as a mirror.
valueReactNode (required)—Value under the label. Pass a formatted string (with tabular-nums when comparing across columns).

Related

Cross-links to atoms and patterns you may reach for next.

  • Provider legend rowInteractive sibling. Use when you need click-to-filter behavior with horizontal scroll.
  • Chart cardCanonical host — StatusLegend goes inside ChartCard's body above the chart.
  • ChartThe chart primitive that renders the series. StatusLegend names the same colors ChartConfig assigns to each dataKey.