015 / RECHARTS / AREA
Comparison Area
Two-series area visualization for comparing a primary magnitude against a reference magnitude across an ordered domain, using restrained overlap, deterministic semantic identity, and shared Y-scale.
- SPEC
- #015
- ENGINE
- Recharts
- FAMILY
- Area
- RENDERER
- svg
- STATUS
- preview
Installation
Checking public registry…
View local registry JSONCopied as source into your project (requires recharts).
Overview
Comparison Area is the comparative-specialized chart of the Plotcn Area family. It visualizes a dominant primary magnitude against a reference magnitude across the same ordered domain, filling both toward a shared baseline while using restrained overlap and deterministic visual hierarchy.
The primary analytical question answered by Comparison Area is:
"How does the primary series compare with the reference across the same domain?"
The secondary analytical question is:
"At this observation, what is the factual difference between them?"
Unlike multi-series stacked charts that accumulate values into an aggregate sum, Comparison Area displays independent magnitudes measured in the exact same unit on a shared Y-axis. The overlap between the two areas communicates comparison—it is not an additive contribution nor a separate third metric.
import { ComparisonArea } from "@/components/charts/recharts/area-comparison"const revenueData = [ { month: "Jan", current: 125, previous: 110 }, { month: "Feb", current: 142, previous: 120 }, { month: "Mar", current: 138, previous: 135 }, { month: "Apr", current: 165, previous: 140 }, { month: "May", current: 158, previous: 162 }, { month: "Jun", current: 184, previous: 155 },]export function MonthlyRevenueComparison() { return ( <ComparisonArea data={revenueData} xKey="month" series={{ primary: { key: "current", label: "2026 (Current)" }, reference: { key: "previous", label: "2025 (Previous)" }, }} primaryColor="var(--chart-1)" referenceColor="var(--chart-2)" valueFormatter={(v) => `$${v.toLocaleString()}k`} showGrid showLegend /> )}Area-Family Positioning
The Plotcn Area family provides five distinct analytical instruments:
| Consideration | Prism Area (011) | Stack Flow Area (012) | Percent Stream Area (013) | Range Area (014) | Comparison Area (015) |
|---|---|---|---|---|---|
| Primary Question | "How much magnitude exists relative to baseline?" | "How do parts and total magnitude combine?" | "How does the composition of the whole evolve?" | "What envelope contains the observations?" | "How does primary compare against reference?" |
| Fill Geometry | Fills between metric and baseline | Fills additive layers from bottom to top | Fills 100% normalized proportional shares | Fills between lower and upper bounds | Fills both toward the same baseline (overlapping) |
| Baseline Role | Configurable baseline ( or min) | Fixed baseline () | Fixed baseline () | No baseline fill; lower bound is floor | Single shared baseline for both roles |
| Series Roles | Single series | additive series | proportional series | Bounded envelope + optional centerline | Exactly two roles: Primary & Reference |
| Overlap Treatment | Not applicable | Stacks without overlap | Stacks to 100% | Single bounded band | Restrained translucent overlap |
Comparison Area vs Twinline Compare (003)
- Twinline Compare: Focuses purely on linear trajectories, precise line crossings, and high-density multi-point inspection where shaded fills would create excessive visual clutter.
- Comparison Area: Focuses on quantitative magnitude relative to a shared baseline. Shaded fills convey volume and cumulative presence, making cumulative gaps and overall scale differences immediately intuitive.
Comparison Model
Restrained Overlap Across Shared Baseline & Single Y-Scale
Primary and Reference:
- Share the exact same horizontal X domain.
- Share the exact same quantitative measurement unit.
- Share the exact same Y scale and zero-reference baseline.
- Overlap with controlled alpha rather than stacking vertically.
Comparison vs Stacking
Why Comparison Areas Must Overlap, Never Stack
Both series fill upward from zero. Visual height truthfully reflects independent period magnitudes ($140k vs $120k).
Primary sits on top of reference. Visual peak reaches $260k, creating the false illusion of a combined $260k revenue total.
A frequent charting anti-pattern is using a stacked area chart when comparing two time periods:
In a stacked area chart, the visual top of the stack would reach $260k when comparing $140k against $120k, misleading viewers into believing that revenue totaled $260k in that period.
In Comparison Area, both series start from the baseline (). At that coordinate, the chart clearly shows two heights: and , with an overlapping shaded region of and an upper primary extension of .
Overlap Treatment
Comparison Area deliberately enforces strict structural hierarchy so both roles remain clearly identifiable even when printed in grayscale or rendered with identical colors:
Primary Role:→ Rendered SECOND (on top)→ Stronger opacity (default: 0.28)→ Solid 2px boundary stroke→ Solid rectangle indicator in legendReference Role:→ Rendered FIRST (underneath)→ Quieter opacity (default: ~0.14)→ Dashed boundary stroke (strokeDasharray="4 3")→ Dashed indicator in legendDifference Semantics
When both primary and reference observations exist at an inspected coordinate, the inspection card computes the factual delta:
- Factual Arithmetic: The difference represents pure arithmetic. It is formatted with a leading sign (
+16,000or−4,200). - Neutral Styling: Plotcn renders deltas in neutral typography. A positive delta is not inherently "good" (green) and a negative delta is not inherently "bad" (red)—in metrics like server latency, defect rates, or infrastructure costs, higher values represent regressions.
- Truthful Missing Handling: If either primary or reference is missing at coordinate , the delta row reports
"Unavailable". Zero is never substituted.
Data Contract
Comparison Area accepts a readonly array of objects. Caller data is never mutated or sorted in place.
export interface RevenueComparisonPoint { month: string // Chronological or ordinal domain key current: number | null // Primary series magnitude previous: number | null // Reference series magnitude}Truthful Missing Values
| Condition at Coordinate | Primary Area | Reference Area | Tooltip Primary | Tooltip Reference | Delta Readout |
|---|---|---|---|---|---|
| Both Valid | Rendered | Rendered | Formatted value | Formatted value | Formatted |
| Primary Missing () | Visual gap | Rendered | "Unavailable" | Formatted value | "Unavailable" |
| Reference Missing () | Rendered | Visual gap | Formatted value | "Unavailable" | "Unavailable" |
| Both Missing () | Visual gap | Visual gap | "Unavailable" | "Unavailable" | "Unavailable" |
| Primary or Reference = 0 | Rendered at | Rendered at | $0 | $0 | Formatted |
Series Contract
Comparison Area requires exactly two semantic roles configured via the series prop:
| Role | Property | Type | Required | Description |
|---|---|---|---|---|
| Primary | key | NumericKeyOf<TData> | Yes | Key in observation records for primary magnitude |
| Primary | label | string | Yes | Descriptive label for primary series (e.g. "Current year") |
| Primary | color | string | Optional | Optional series-level color override |
| Reference | key | NumericKeyOf<TData> | Yes | Key in observation records for reference magnitude |
| Reference | label | string | Yes | Descriptive label for reference series (e.g. "Previous year") |
| Reference | color | string | Optional | Optional series-level color override |
Color Customization
Comparison Area accepts semantic CSS theme tokens or explicit custom color overrides:
<ComparisonArea data={data} xKey="month" series={{ primary: { key: "current", label: "Current year" }, reference: { key: "previous", label: "Previous year" }, }} primaryColor="var(--chart-1)" referenceColor="var(--chart-2)" selectionColor="var(--chart-selection)" fillOpacity={0.28}/>- Theme Synchronization: Changing
primaryColororreferenceColorinstantly updates fills, boundaries, active inspection markers, and legend indicators without remounting or resetting inspection state. - Same-Color Distinction: If
primaryColor === referenceColor, the primary solid 2px stroke and 0.28 opacity remain readily distinguishable from the reference dashed 1.5px stroke and 0.14 opacity.
Props Reference
| Property | Type | Default | Description |
|---|---|---|---|
data | readonly TData[] | [] | Readonly array of observation records. Caller data is never mutated. |
xKey | keyof TData & string | required | Property name representing horizontal domain coordinates. |
series | ComparisonAreaSeries<TData> | required | Semantic configuration defining primary and reference keys and labels. |
height | number | string | 320 | Container height in pixels or CSS units. |
curve | "monotone" | "linear" | "step" | "monotone" | Shared interpolation curve applied identically to both series. |
domain | [number, number] | "auto" | "auto" | Shared vertical domain override covering both roles. |
primaryColor | string | var(--chart-1) | Color for primary area fill, boundary stroke, and legend indicator. |
referenceColor | string | var(--chart-2) | Color for reference area fill, boundary stroke, and legend indicator. |
fillOpacity | number | 0.28 | Primary area fill opacity. Reference opacity derives quieter (~0.14). |
showDelta | boolean | true | Whether to render factual difference arithmetic in tooltips. |
deltaType | "absolute" | "percentage" | "both" | "both" | Formatting style for comparison delta. |
showGrid | boolean | true | Whether to render horizontal Cartesian reference rules. |
showXAxis | boolean | true | Whether to render horizontal domain tick labels. |
showYAxis | boolean | true | Whether to render vertical metric scale ticks. |
showLegend | boolean | true | Whether to render series identity legend with structural samples. |
interactiveLegend | boolean | true | Enables toggling role visibility by clicking legend items. |
lockableTooltip | boolean | true | Enables persistent tooltip pinning on click, tap, or Enter/Space. |
motion | boolean | { duration?: number } | true | Entry reveal animation. Automatically bypassed under reduced motion. |
valueFormatter | (value: number) => string | n.toLocaleString() | Formatter for metric values and comparison delta. |
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.
<ComparisonArea
data={data}
xKey="date"
series={{
primary: { key: "current", label: "Current year" },
reference: { key: "previous", label: "Previous year" },
}}
/>Shared interpolation algorithm applied identically to both areas.
curve="monotone"Default: "monotone"Color for primary area fill, solid boundary stroke, and legend sample.
primaryColor="var(--chart-1)"Default: "var(--chart-1)"Color for reference area fill, dashed boundary stroke, and legend sample.
referenceColor="var(--chart-2)"Default: "var(--chart-2)"Primary area fill opacity (0.05 to 1.0). Reference opacity derives quieter (~0.14).
fillOpacity={0.28}Default: 0.28Whether to display factual comparison arithmetic (primary − reference) in the tooltip.
showDelta={true}Default: trueFormat for comparison delta readout in the inspection card.
deltaType="both"Default: "both"Whether to render horizontal Cartesian reference rules.
showGrid={true}Default: trueWhether to render the series identity legend with non-color structural samples.
showLegend={true}Default: trueEnables clicking legend items to toggle role visibility.
interactiveLegend={true}Default: trueEnables persistent tooltip pinning on click, tap, or Enter/Space.
lockableTooltip={true}Default: true| Property | Type | Default | Required | Description |
|---|---|---|---|---|
dataReq | readonly TData[] | [] | Yes | Readonly array of observation records. Caller data is never mutated or sorted in place. |
xKeyReq | keyof TData & string | — | Yes | Property name on data records for horizontal domain coordinates. |
seriesReq | ComparisonAreaSeries<TData> | — | Yes | Explicit semantic configuration defining primary and reference roles. |
heightOpt | number | string | 320 | No | Container height in pixels or standard CSS dimension strings. |
curveOpt | "linear" | "monotone" | "step" | "monotone" | No | Shared interpolation algorithm applied identically to both areas. |
primaryColorOpt | string | "var(--chart-1)" | No | Color for primary area fill, solid boundary stroke, and legend sample. |
string | "var(--chart-2)" | No | Color for reference area fill, dashed boundary stroke, and legend sample. | |
string | "var(--chart-selection)" | No | Color for active locked inspection crosshair. | |
fillOpacityOpt | number | 0.28 | No | Primary area fill opacity (0.05 to 1.0). Reference opacity derives quieter (~0.14). |
showDeltaOpt | boolean | true | No | Whether to display factual comparison arithmetic (primary − reference) in the tooltip. |
deltaTypeOpt | "absolute" | "percentage" | "both" | "both" | No | Format for comparison delta readout in the inspection card. |
showGridOpt | boolean | true | No | Whether to render horizontal Cartesian reference rules. |
showXAxisOpt | boolean | true | No | Whether to render horizontal category scale ticks. |
showYAxisOpt | boolean | true | No | Whether to render vertical metric scale ticks. |
showLegendOpt | boolean | true | No | Whether to render the series identity legend with non-color structural samples. |
boolean | true | No | Enables clicking legend items to toggle role visibility. | |
boolean | true | No | Enables persistent tooltip pinning on click, tap, or Enter/Space. | |
"gap" | "connect" | "gap" | No | Handling of missing / null values. | |
(value: number) => string | v => v.toLocaleString() | No | Custom formatter for metric values and delta readouts. | |
xFormatterOpt | (value: any) => string | — | No | Custom formatter for horizontal domain tick labels. |
motionOpt | boolean | { duration?: number } | true | No | Controls entry reveal animations. Automatically bypassed under reduced motion. |
titleOpt | string | "Comparison Area Chart" | No | Accessible heading announced to screen readers. |
descriptionOpt | string | — | No | Extended descriptive summary for assistive technologies. |
Component Variants & Edge States
Production cookbooks showcasing configuration variants alongside verified handling of loading, empty data, and network error states.
Monthly Revenue Comparison
Monthly recurring revenue comparing 2026 (current year) against 2025 (previous year) across identical months.
Same-Color Structural Distinction
Demonstrates non-color differentiation: even when both series use identical colors, primary (solid border, stronger fill) and reference (dashed border, quieter fill) remain immediately readable.
Crossing Trajectories
Primary and reference series cross multiple times over the domain, validating that restrained opacity preserves legibility throughout intersections without flashy blend modes.
Independent Missing Values
Truthful gap rendering when observations are missing in either series. A missing reference leaves the primary intact and marks difference unavailable.
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
Comparison Area preserves both primary and reference layers, non-color structural samples, and active inspection slice across all device widths down to 320px.
Spacious overlap geometry, full domain ticks, horizontal legend, and comprehensive inspection tooltip with delta readout.
Adaptive domain tick thinning, preserved primary/reference hierarchy, and wrapped legend controls.
Compact gutters, full dual-layer area geometry without dropping either role, and compact stacked tooltip preventing horizontal overflow.
Accessibility & Navigation Standards
Single keyboard tab stop on root figure with ArrowLeft, ArrowRight, Home, End, Enter/Space, and Escape shortcuts.
Container mounts as region with explicit assistive label.
Primary solid stroke (2px) versus Reference dashed stroke (1.5px, 4 3), opacity attenuation, and structured data table ensure complete non-color accessibility.
Embeds visually hidden summary (.sr-only) declaring: “Announces domain coordinate, primary value, and reference value. Factual arithmetic delta is narrated without good/bad value judgments.”
All entrance animations immediately bypass when prefers-reduced-motion is detected in user system preferences.
| Key | Action |
|---|---|
| ArrowRight | Inspect next chronological observation across the domain. |
| ArrowLeft | Inspect previous chronological observation across the domain. |
| Home | Jump inspection directly to the first observation. |
| End | Jump inspection directly to the final observation. |
| Enter / Space | Lock or unlock persistent inspection at the active coordinate. |
| Escape | Release locked selection and dismiss active inspection tooltip. |
Data Safety Guarantees
- Deterministic Semantic Roles: Primary and Reference represent fixed semantic roles. Neither role inherits the other's identity when hidden.
- One Shared Y Scale: Primary and Reference are always measured against the exact same scale and baseline. Dual-axis scaling is prohibited.
- No Stacking Distortion: Primary and Reference overlap independently. Values are never added together to fabricate a combined sum.
- No Fabricated Data: Missing values () produce explicit breaks in the area geometry; zero is never substituted.
- Finite Coordinates Only: Non-finite values (
NaN,Infinity) are sanitized before rendering SVG paths. - Neutral Comparison: Difference arithmetic is presented factually without forced positive/negative value judgments.
- Accessibility Disclosure: Structured HTML data table disclosure provides full non-visual access to all primary, reference, and difference values.
Internal Architecture & File Dependencies
Source-first ownership model. Inspect the exact component call tree, dependencies, and full implementation below.
Handles container dimension measurement and SVG viewBox sizing
Coordinates scales, Cartesian grid, reference area, primary area, and shared tooltip
Encodes structural differences (solid vs dashed) and supports visibility toggling