025 / RECHARTS / BAR & COLUMN
Variance Bars
Actual-versus-plan delta bars centered on a truthful zero-variance baseline, with neutral signed semantics and auditable source values.
- SPEC
- #025
- ENGINE
- Recharts
- FAMILY
- Bar & Column
- RENDERER
- svg
- STATUS
- preview
Installation
Checking public registry…
View local registry JSONCopied as source into your project (requires recharts).
Overview
Variance Bars visualizes the categorical arithmetic difference between an observed measure and an explicit plan or reference value:
A positive bar indicates an actual value numerically above plan; a negative bar indicates an actual value numerically below plan; and zero represents exact parity with plan.
Terminology Clarification: In Plotcn, variance refers exclusively to categorical actual-versus-plan arithmetic delta. It does not mean statistical variance, sample variance, or dispersion around a mean.
Governing Principle
Variance Bars visualizes the arithmetic difference between an actual value and an explicit plan/reference value. Zero means actual equals plan, positive means actual is numerically above plan, and negative means actual is numerically below plan. Plotcn must never automatically translate those directions into good/bad, favorable/unfavorable, success/failure, profit/loss, or healthy/unhealthy.
Installation
Checking public registry…
View local registry JSONCopied as source into your project (requires recharts).
Usage
import { VarianceBars } from "@/components/charts/recharts/bar-variance"const data = [ { segment: "Enterprise", actual: 124, plan: 110 }, { segment: "Mid-market", actual: 92, plan: 100 }, { segment: "SMB", actual: 74, plan: 74 }, { segment: "Public Sector", actual: 68, plan: 72 }, { segment: "Partners", actual: 81, plan: 75 },]export function BudgetVarianceExample() { return ( <VarianceBars data={data} categoryKey="segment" series={{ actualKey: "actual", planKey: "plan", label: "Revenue Variance", valueFormatter: (v) => `$${v}M`, varianceFormatter: (v) => `${v > 0 ? "+" : ""}$${v}M`, }} /> )}Variance Model
Variance Bars derives one signed quantitative delta bar from two caller-supplied fields: actualKey and planKey.
Actual − Plan = Signed Variance
Flow diagram showing how consumer-supplied actual and plan values are subtracted to produce the derived signed variance bar, contrasting arithmetic delta with statistical variance.
Actual vs Plan → Delta
Every observation resolves to one of three canonical factual positions:
Three Canonical States: Above, Equal, Below Plan
Comparison diagram illustrating actual 120 vs plan 100 yielding positive 20, actual 100 vs plan 100 yielding zero, and actual 80 vs plan 100 yielding negative 20.
- Above Plan: Actual > Plan ⇒ Variance > 0. Bar extends upward (vertical) or rightward (horizontal).
- On Plan (Equal): Actual = Plan ⇒ Variance = 0. No quantitative bar is rendered; the baseline itself communicates equality.
- Below Plan: Actual < Plan ⇒ Variance < 0. Bar extends downward (vertical) or leftward (horizontal).
Zero-Variance Baseline
The zero line is a semantic equality reference, not optional background decoration.
Zero Baseline as Equality Anchor
Diagram showing the prominent zero baseline as the dividing reference line between negative and positive variance, signifying actual equals plan.
- The zero line defaults to the structural
--chart-axistoken. - It remains visually stronger than ordinary grid lines but distinct from active focus rings.
- Zero actual, zero plan, and zero variance are all legitimate, distinct states.
Positive, Zero, and Negative Geometry
Symmetric Bar Extrusion Around Zero Reference
SVG demonstrating how positive bars extrude outward upward or rightward, negative bars extrude downward or leftward, and zero values produce no fake bar width.
- Positive bars extrude outward in the positive direction.
- Negative bars extrude outward in the negative direction.
- Categories with zero variance produce no artificial minimum width or height, preventing distorted visual arithmetic while remaining fully interactive via category hit bands.
Direction Is Not Favorability
A common design pitfall in financial dashboards is treating all positive variances as "good" (green) and negative variances as "bad" (red).
Numerical Direction ≠ Business Favorability
Critical diagram contrasting revenue variance of plus 20 with operating cost variance of plus 20, demonstrating why Plotcn must never equate positive direction with good or negative direction with bad.
- Revenue: Actual
$120Mvs Plan$100M→ Variance+$20M(Surplus). - Infrastructure Cost: Actual
$120Kvs Plan$100K→ Variance+$20K(Budget overrun).
Both have identical arithmetic direction (+20), but opposite operational implications. Plotcn strictly reports objective mathematical positions (Above plan, Below plan), leaving business interpretation to the consuming application.
Negative Input Arithmetic
Actual and plan values are not required to be non-negative. When dealing with signed inputs (such as debt, deficits, or sub-zero temperatures), variance direction is derived strictly by subtraction:
Negative Input Values Obey Arithmetic Delta
Mathematical diagram demonstrating that actual negative 80 minus plan negative 100 equals positive 20, proving that variance direction comes from subtraction and not raw input sign.
Actual = -80, \quad Plan = -100 \implies (-80) - (-100) = +20Even though the observed actual value is negative, it is numerically above the reference plan, yielding a positive variance bar.
Pairwise Validity & Missing Data
A valid variance requires both actual and plan to be finite numbers (Number.isFinite).
Pairwise Validity: Missing Pair Yields Unavailable
Two-panel diagram showing that missing actual with valid plan, or valid actual with missing plan, produces an unavailable variance rather than coercing missing data to zero.
- Missing Actual: If
actualisnullandplanis 100, variance is unavailable. Never infer 0 − 100 = −100. - Missing Plan: If
actualis 80 andplanisnull, variance is unavailable. Never infer 80 − 0 = +80. - Non-Finite Values:
NaN,Infinity, and-Infinityare rejected as unavailable and never entered into SVG coordinates.
Symmetric Domain Policy (Policy B)
To guarantee that equal absolute deviations (e.g. +40 and −40) receive equal visual bar lengths, Plotcn applies Policy B:
Symmetric Zero-Centered Domain Preserves Equal Visual Magnitude
Comparison contrasting an asymmetric data domain with a symmetric zero-centered domain [-80, +80], proving that equal absolute values like plus 40 and minus 40 receive equal visual bar lengths.
- Mixed Signs: Symmetric domain
[-extent, +extent]centered at zero, whereextent = max(|min|, |max|). - Positive Only:
[0, safeMax](preserves zero without wasting the negative half of the canvas). - Negative Only:
[safeMin, 0](preserves zero without wasting the positive half of the canvas). - All Zero: Safe expansion
[-1, 1]centered at zero.
Interaction & Category Band Hit Region
Zero-variance categories, tiny deviations, and rows with missing data must remain easily inspectable without distorting bar geometry.
Category Band Hit Targets Keep Zero/Tiny Bars Accessible
Interaction diagram showing how the entire categorical band acts as the hit target, allowing zero or tiny variance bars to remain inspectable on touch devices and desktop pointers.
- Pointer and touch hit testing are bound to the full category band (36–48px).
- Tiny bars do not require sub-pixel pointer accuracy.
- Vertical page scrolling is preserved on mobile devices (
touch-action: pan-y).
Layout: Vertical vs Horizontal
Both orientations are first-class, specialized compositions:
Vertical vs Horizontal Orientation
Side-by-side comparison illustrating vertical orientation best for standard metrics vs horizontal orientation best for long category labels and compact scorecards.
- Vertical (
orientation="vertical", default): Ideal for short category labels (quarters, regions) in standard dashboard layouts. Traversal usesArrowLeftandArrowRight. - Horizontal (
orientation="horizontal"): Ideal for long department names, ledger accounts, and narrow mobile viewports. Traversal usesArrowUpandArrowDown.
Rendering Architecture
VarianceBars Rendering & Accessibility Pipeline
Complete rendering architecture flowchart tracing consumer data through pair validation, arithmetic subtraction, symmetric domain resolution, Recharts SVG rendering, and offscreen accessible tables.
Props Reference
| Property | Type | Default | Description |
|---|---|---|---|
data | readonly TData[] | Required | Source dataset. Array order is strictly caller-preserved. |
categoryKey | keyof TData & string | Required | Property key representing the discrete category label. |
series | VarianceBarSeries<TData> | Required | Semantic series contract declaring actualKey and planKey. |
orientation | "vertical" | "horizontal" | "vertical" | Axis arrangement for categories and quantitative variance bars. |
height | number | string | 340 | Chart container height in pixels or CSS dimension. |
domain | [number, number] | "auto" | "auto" | Quantitative scale bounds. Must include zero. |
positiveColor | string | "var(--chart-1)" | Fill color for bars where actual is numerically above plan. |
negativeColor | string | "var(--chart-2)" | Fill color for bars where actual is numerically below plan. |
zeroColor | string | "var(--chart-axis)" | Stroke color for the zero baseline reference rule. |
selectionColor | string | "var(--chart-selection)" | Stroke emphasis for the currently focused category bar. |
showGrid | boolean | true | Whether to render subtle background Cartesian gridlines. |
showZeroLine | boolean | true | Whether to render the prominent zero reference line. |
showLegend | boolean | false | Whether to render the structural directional legend. |
valueLabel | "none" | "variance" | "auto" | "none" | Permanent outward numeric variance label policy. |
tooltipMode | "variance" | "full" | "full" | Tooltip detail level ("full" audits actual, plan, and variance). |
maxBarSize | number | 36 | Maximum bar thickness in pixels. |
motion | boolean | { duration?: number } | true | Animation toggle (honors prefers-reduced-motion). |
loading | boolean | false | Whether to render the skeleton loading state. |
Props Reference & Interactive Prop Explorer
Inspect every component property, customize semantic color roles live with instant visual feedback, and copy production-ready code with active prop configurations.
Colors & Appearance Configuration
Customize primary, reference, or annotation series colors. Defaults derive from Plotcn theme tokens.
<VarianceBars
data={data}
categoryKey="segment"
series={{
actualKey: "actual",
planKey: "plan",
label: "Revenue Variance",
}}
/>Arrangement of categorical and quantitative axes.
orientation="vertical"Default: "vertical"Whether to render subtle background Cartesian grid lines.
showGrid={true}Default: trueWhether to render the prominent zero reference baseline.
showZeroLine={true}Default: trueWhether to display the directional legend.
showLegend={false}Default: falsePolicy for rendering inline numeric variance labels.
valueLabel="none"Default: "none"Tooltip depth ("full" displays actual, plan, and variance).
tooltipMode="full"Default: "full"| Property | Type | Default | Required | Description |
|---|---|---|---|---|
dataReq | readonly TData[] | [] | Yes | Array of categorical data records. Order is strictly preserved. |
categoryKeyReq | keyof TData & string | — | Yes | Key on data records representing the discrete category label. |
seriesReq | VarianceBarSeries<TData> | — | Yes | Series definition specifying actualKey, planKey, label, and optional formatters. |
orientationOpt | "vertical" | "horizontal" | "vertical" | No | Arrangement of categorical and quantitative axes. |
heightOpt | number | string | 340 | No | Chart container height in pixels or CSS dimension string. |
domainOpt | [number, number] | "auto" | "auto" | No | Quantitative domain bounds. Follows Policy B symmetry for mixed signs. |
string | "var(--chart-1)" | No | Fill color for bars where actual is numerically above plan. | |
string | "var(--chart-2)" | No | Fill color for bars where actual is numerically below plan. | |
zeroColorOpt | string | "var(--chart-axis)" | No | Stroke color for the zero baseline reference line. |
string | "var(--chart-selection)" | No | Stroke emphasis color for the currently focused category bar. | |
showGridOpt | boolean | true | No | Whether to render subtle background Cartesian grid lines. |
showZeroLineOpt | boolean | true | No | Whether to render the prominent zero reference baseline. |
showLegendOpt | boolean | false | No | Whether to display the directional legend. |
valueLabelOpt | "none" | "variance" | "auto" | "none" | No | Policy for rendering inline numeric variance labels. |
tooltipModeOpt | "variance" | "full" | "full" | No | Tooltip depth ("full" displays actual, plan, and variance). |
motionOpt | boolean | { duration?: number } | true | No | Animation toggle honoring reduced-motion preferences. |
Component Variants & Edge States
Production cookbooks showcasing configuration variants alongside verified handling of loading, empty data, and network error states.
Revenue vs Plan by Segment
Standard business scorecard comparing segment revenues against financial budget plans.
Operating Cost Variance (Horizontal)
Compact horizontal scorecard for operating budget variance with long department labels.
Skeletons indicate runtime fetch or pending data queries.
Handles empty collections ([]) gracefully without crashing.
Graceful failure banner when data source or script fails.
Container-Driven Breakpoints
VarianceBars uses container-driven geometry via ResizeObserver and SVG viewbox scaling. Zero baseline and equal absolute bar lengths are preserved at every width.
Category labels truncate gracefully or reflow into horizontal scorecard rows; tooltips clamp within container width with compact typography.
Standard vertical column composition with reduced tick density on the quantitative scale and full category band touch hit testing.
Full analytical layout displaying quantitative gridlines, outward value labels, and rich actual/plan/delta tooltip inspection.
Accessibility & Navigation Standards
Semantic figure region with single tab stop, orientation-specific arrow-key traversal, Home/End navigation, polite ARIA announcements, and an offscreen structured HTML table disclosing actuals, plans, and variances.
Container mounts as region with explicit assistive label.
Direction is encoded geometrically by extrusion relative to the center zero baseline (above/right for positive, below/left for negative). Color serves purely as supplementary visual identity.
Embeds visually hidden summary (.sr-only) declaring: “Announces category name, observed actual value, reference plan, derived signed variance, and factual position relative to plan.”
All initial entrance animations are bypassed immediately when prefers-reduced-motion is detected.
| Key | Action |
|---|---|
| ArrowLeft / ArrowRight | Traverse categories in vertical orientation |
| ArrowUp / ArrowDown | Traverse categories in horizontal orientation |
| Home | Jump focus to the first category |
| End | Jump focus to the last category |
| Escape | Clear active category inspection |
Internal Architecture & File Dependencies
Source-first ownership model. Inspect the exact component call tree, dependencies, and full implementation below.
Provides responsive sizing and token styling