Area chart
Purpose
An Area chart shows how a value accumulates over time, with the region beneath the line filled to emphasise volume. Use it when the cumulative quantity is the takeaway, or when several series stacked together sum to a meaningful total. Do NOT use an Area chart when the trajectory of the line is the primary read and the volume under it is irrelevant — use a Line chart instead. Do NOT use an Area chart with a stacked layout when any series contains negative values — negative numbers make the shared baseline jump and the composition unreadable.
Anatomy
An Area chart is composed of:
- Title (required at md and lg): Headline label above the chart. Wraps to two lines; truncates with ellipsis beyond that. Optional at sm.
- Subtitle (optional): One line of context under the title. Does not wrap.
- Headline metric (optional): A KPI tile in the chart header — one summary number alongside the area. Number is the takeaway; the area shows the journey.
- Action menu (optional): Per-widget controls — export, refresh, filter — pinned to the top-right corner.
- Y axis: Numeric values. Always begins at zero. Unlike the Line chart, there is no exception — a floating baseline misrepresents the filled volume.
- X axis: Time or continuous interval. Tick labels follow the Force UI date formatting rules and respond to the
xFormatoverride. - Gridlines: Horizontal only by default, anchored to y-tick positions.
- Area marks: A filled region per series. In the
singlevariant, one region bounded above by an outline stroke and below by zero. In thestackedvariant, each region is bounded above by its outline stroke and below by the previous series' top boundary. - Outline stroke: The line along the top boundary of each filled area. Visually distinct from the fill; carries series color at full opacity. In the stacked variant with three or more series, each series also uses a distinct stroke dash pattern (see Accessibility) so bands are distinguishable by shape as well as color.
- Crosshair: A 1px vertical line that tracks the pointer along the x axis, anchoring the tooltip content to the nearest x value.
- Tooltip: Appears on hover or keyboard focus. Shows the x label, then one row per visible series — a color swatch, the series name, and the formatted y value. In the
stackedvariant, a cumulative total row is appended at the bottom. - Legend: A row of color swatches with series labels, always positioned below the chart. Required whenever more than one series is shown at md or lg density.
- Reference line (optional): A dashed horizontal threshold or average overlay. 1px dashed
2px 2px,--force-color-border-muted. Label right-aligned to the plot edge. - Empty, loading, error, and no-permission overlays: Replace the plot area when data is unavailable. Title and header always remain visible.
When to use
Use an Area chart when:
- The reader is following a value's cumulative volume across time, or how several series sum to a total.
- The x axis is continuous: a date range, a timestamp sequence, a build counter, a sprint cadence.
- At least two data points exist per series so a shape can be drawn.
- No more than five series are stacked (
stackedvariant), or no more than seven for thesinglevariant.
Do NOT use an Area chart when:
- The trajectory of the line is the primary question and volume is irrelevant — use a Line chart.
- Negative values are present in a stacked layout — stacked areas cannot represent negatives. Use a Line chart or a grouped Bar chart instead.
- The reader needs to read individual series values precisely — stacked areas make per-series values harder to compare than a Line chart.
- The x axis is categorical (products, regions, teams) — use a Bar chart.
- Only one data point exists — use a KPI tile.
- The widget is rendered below 320px wide — use the Sparkline variant or a KPI tile.
Data requirements
| Requirement | Constraint | Behavior at the limit or when violated |
|---|---|---|
| Required fields | x (time or continuous), y (numeric, non-negative when stacked) |
If either is missing, render the Empty state with an explanation. |
| Accepted x types | ISO datetime, epoch ms, or numeric ordinal | Strings are not accepted. Pass categorical x to Bar chart instead. |
| Accepted y types | Number for single. Non-negative number for stacked. |
Nulls are skipped; the area breaks across the gap with reduced opacity. Nulls are never silently zeroed — a zero would change the visual baseline. |
| Minimum data points | 2 per series | Fewer than 2 falls back to a KPI tile with the single value passed through. |
| Maximum data points | 1 000 per series (SVG mode), 10 000 (canvas mode) | Above the limit the chart downsamples and shows a banner explaining the reduced resolution. |
| Series count limit | 5 for stacked, 7 for single and forecast |
Above the limit, group remaining series into "Other" and provide a "view all" link to the underlying table. |
| Negative values in stacked | Not allowed | A stacked payload containing negatives renders the Error state with a note redirecting to the Line chart. |
| Sort order | Chart sorts x ascending regardless of input order | The component cannot rely on the caller to pre-sort. |
| Aggregation | No client-side aggregation. Caller provides values at the desired interval. | If the interval is too dense for the rendered width, the chart downsamples and labels the new interval. |
Configuration
| Prop | Type | Default | Purpose |
|---|---|---|---|
| CONTENT | |||
title |
string |
required | Headline label above the chart. Wraps to two lines, then truncates with ellipsis. |
subtitle |
string |
undefined |
Optional one-line context under the title. Does not wrap. |
headlineMetric |
{ value, label, delta } |
undefined |
Optional KPI rendered in the chart header. |
| DATA | |||
data |
Array<{x, y, series?}> |
required | The data payload. Schema defined in Data requirements above. |
groupBy |
string |
undefined |
Optional field name to split data into series. Also determines stack order in the stacked variant. |
referenceLines |
Array<{ value, label, style? }> |
[] |
Horizontal threshold or comparison lines overlaid on the plot area. |
xFormat |
string |
'auto' |
Custom date or numeric format for x-axis tick labels. Defaults to the Force UI date formatting rules. |
yFormat |
string |
'auto' |
Custom number format for y values and tooltip. Supports: 'currency', 'percent', 'abbreviated', 'raw'. |
| VISUAL | |||
variant |
'single' | 'stacked' | 'forecast' | 'sparkline' |
'single' |
Approved variants documented in the Variants section. |
colorMapping |
Record<series, token> |
system | Overrides the automatic categorical color mapping for this chart instance. |
density |
'sm' | 'md' | 'lg' |
'md' |
Widget density. Affects type sizes, padding, tick density, and label rotation. |
theme |
'light' | 'dark' | 'auto' |
'auto' |
Overrides the dashboard theme for this instance. |
| BEHAVIORAL | |||
legend |
'bottom' | 'none' |
'bottom' when multi-series; 'none' when single series |
Controls legend visibility. Always positioned below the chart when shown. |
tooltip |
boolean |
true |
When false, hover and focus produce no tooltip. |
onMarkClick |
function |
undefined |
Optional drill-down callback. When set, the point on the outline stroke at the crosshair becomes focusable; clicking fires the handler with the data row. |
exportable |
boolean |
true |
Whether the action menu exposes an Export option. |
interactive |
boolean |
true |
Master switch. When false, the chart renders as a static image — no hover, tooltip, or keyboard behavior. Use for print and email contexts. |
zoomable |
boolean |
false |
When true, scroll zooms the x axis, drag pans, and a reset affordance returns to the full range. |
crossFilter |
boolean |
false |
When true, selecting a region updates other widgets on the dashboard that share the same data binding. |
Variants
Four approved variants, selected via the variant prop.
Single
The most common configuration. One filled area per chart, bounded above by an outline stroke and below by the zero baseline. Fill uses the series' chart color at 40% opacity; outline stroke is the same color at full opacity. Use when the volume under a single time series is the takeaway — data ingest over time, CPU utilization, request rate.
Stacked
Multiple series stacked vertically on a shared zero baseline, each bounded by its own outline stroke. The fills sum to a total at every x point. Use when the composition of the total is the question — "how is this total distributed across components?" The stack order follows the groupBy field or, if unspecified, the order series appear in the data. The topmost series represents the total.
Legend items in this variant are ordered to match the stack from bottom to top. Clicking a legend item toggles its series; the remaining series reflow to fill the freed vertical space while maintaining the total shape.
Forecast
Divides each series at a labeled transition point. Observed data renders with full-opacity fill and solid outline stroke. Projected data renders at 30% opacity fill and 40% opacity outline stroke with a 4px 4px dash. The transition is marked with a short vertical dotted rule and a label ("Today" or "Forecast start"). Use for actual-vs-projected patterns — projected data ingest volume, forecast cloud spend.
This variant works with both single and stacked data: pass stacked data to data along with variant="forecast" and the forecast treatment applies to all series simultaneously.
Sparkline
A minimal area shape with no axes, no legend, no title, no tooltip, and no padding. The fill and outline stroke are shown at full opacity; the chart reduces to its silhouette. At sm density (< 320px), the chart enters a sparkline-like mode automatically — no axes, outline stroke only, fill at 30% opacity, tooltip on long press only. Use the sparkline variant explicitly for table cells, KPI tiles, or constrained widgets where only the trend shape is meaningful.
With headline metric
Not a separate variant — use variant="single" (or "stacked") and set headlineMetric. The KPI number is the primary takeaway; the area shows the cumulative path to that number.
With reference line
Not a separate variant — use referenceLines alongside any variant. Each reference line is a 1px dashed horizontal stroke in --force-color-border-muted with a right-aligned label.
States
The title and chart header always remain visible. Only the plot area changes.
Default (data loaded): Area fills and outline strokes are drawn. Null gaps in any series break the outline stroke and fill; the gap renders at reduced opacity (--force-opacity-subtle, 0.7) — never zeroed, because a silent zero would shift the visual baseline.
Loading: Data is being fetched. Render skeleton bars — a set of filled rectangles at varying heights inside the plot area, mimicking the filled chart shape — in --force-color-bg-muted. Do not use a spinner for charts taking longer than 200ms.
Empty: No data for the selected period. Show a brief explanation and, where applicable, a call to action. Use the EmptyState component inside the plot area.
Error: Data fetch failed. Show an explanation and a "Retry" button. Never silently fall back to the Empty state.
No permission: The viewer cannot access the underlying data. Replace the entire chart with a locked-state illustration and the message "You do not have access to this data." Do not expose any values or partial data.
Partial data: Some series or time intervals are missing. Render available data, break the affected fill at each gap, and add an inline banner below the chart explaining the missing period.
Single data point: Fewer than two points exist. Fall back to the KPI tile component with the single value passed through.
Stacked with negatives (error): A stacked variant payload containing negative y values cannot render correctly. Show an error overlay explaining the constraint ("Stacked areas require non-negative values") and suggest switching to a Line chart for data with negatives.
Interaction
| Behavior | Specification |
|---|---|
| Hover | The crosshair tracks the pointer along the x axis. The nearest point on the outline stroke is highlighted with a filled marker at full opacity; all other series dim to --force-opacity-subtle (0.7). |
| Tooltip | Floats approximately 12px from the cursor. Content anchored to the nearest x value: x label at top, one row per visible series (color swatch, series name, formatted value), and — in the stacked variant — a cumulative total row at the bottom. Opens on hover or keyboard focus; closes on pointer leave or Escape. |
| Touch | Long press opens the tooltip. Tap elsewhere closes it. |
| Mark click | No-op by default. When onMarkClick is set, the point on the outline stroke at the crosshair becomes focusable and clicking fires the handler with the corresponding data row. |
| Legend item click | Toggles that series' visibility. In the stacked variant, remaining series reflow so their fills expand to fill the freed vertical space while preserving relative proportions. |
| Zoom and pan | Off by default. When zoomable is true, scroll zooms the x axis, drag pans, and a reset affordance returns to the full range. |
| Cross-filter | Off by default. When crossFilter is true, selecting a region updates other widgets sharing the same data binding. |
| Keyboard navigation | Tab focuses the chart container. Left and Right arrows step through x values, opening the tooltip at each position. Enter fires onMarkClick if set. Escape closes the tooltip and returns focus to the chart container. Continued tabbing moves through legend items, then the action menu, then out of the chart. |
Accessibility
| Requirement | Specification |
|---|---|
| Color contrast | Every foreground and background pair meets WCAG 2.2 AA. Tokens in this spec resolve to compliant pairs. Custom colorMapping values must not break contrast against either the area fill or the outline stroke; violations are rejected at design review. |
| Color-blind safety | Categorical palette passes Deuteranopia, Protanopia, Tritanopia, and Achromatopsia simulation. In the stacked variant with three or more series, outline strokes use distinct dash patterns per series so bands are differentiable by shape as well as color: series 1 solid, series 2 dashed 4px 4px, series 3 dotted 2px 2px, series 4 long-dashed 6px 2px, series 5 dash-dot 6px 2px 2px 2px. Color is never the only signal. |
| Screen reader | The chart element has an accessible name (aria-label) derived from title. A summary sentence is exposed to assistive technology (e.g., "Cloud spend by provider, last 30 days. Total peaked at $112k on May 5."). A data table fallback is reachable via a "View as table" affordance on keyboard focus. |
| Keyboard reachability | Every interaction is reachable via keyboard. Tab order: chart container → legend items (left to right) → action menu. |
| Focus indication | A visible focus ring (--force-shadow-focus-ring + --force-color-border-focus) on the chart container, each legend item, and each focusable outline-stroke marker. Focus state is visually distinct from hover. |
| Reduced motion | When prefers-reduced-motion: reduce is set, all draw-in animations, stacked-reflow transitions, and forecast-band animations are removed. Tooltip and focus states appear immediately. |
| Text scaling | The component reflows at up to 200% text size without clipping or overlap. Axis labels collapse first, then tick density reduces, then the legend wraps. |
Sizing and responsive behavior
| Density | Width range | Use case | What changes |
|---|---|---|---|
Small (sm) |
< 320px | Narrow inline widget | No axes. Outline stroke only, fill at 30% opacity. Tooltip on long press only. |
Medium (md) |
320–599px | Standard dashboard widget | Compact axis labels. Numbers abbreviated. Legend wraps below. Tooltip shows one row per series (plus total for stacked). |
Large (lg) |
≥ 600px | Full-width report | Full axis labels. Multiple gridlines. Legend below. Tooltip shows extended metadata including the cumulative total for stacked. |
Guidance
Choose the variant based on the question:
- Single: "What is the cumulative volume of this metric over time?" — one filled area, volume is the read.
- Stacked: "How is this total composed across components?" — multiple bands summing to a total, composition is the read.
- Forecast: "Where is this volume heading?" — solid past, lighter projected, explicit transition label.
- Sparkline: "What is the shape of this trend?" — no chrome, only the silhouette.
Common mistakes to avoid:
- Do NOT truncate the y axis. A filled area with a floating baseline visually exaggerates the magnitude even more than a line chart does. Y axis always starts at zero.
- Do NOT stack more than five series. Below five bands the lower areas flatten to the point where the reader cannot follow any single one. Group the rest into "Other."
- Do NOT use
stackedwhen any series contains negative values. The baseline jump makes the composition unreadable. Use a Line chart or grouped Bar chart for data with negatives. - Do NOT use a stacked area chart when the reader needs to compare individual series values precisely. Stacked areas are only easy to read for the bottom series and the total — intermediate series are hard to judge. Use a multi-series Line chart instead.
- Do NOT use
area: trueon a Line chart as a substitute for thestackedvariant. The Line chart area prop is a visual softener for a single series; it does not support stacking or the associated tooltip, legend, and reflow behaviors.
Token usage
Area fills
- Fill color:
--force-color-chart-1through--force-color-chart-6at 40% opacity - Forecast projected portion: fill at 30% opacity (from the already-reduced 40%, giving ~12% effective opacity)
- Null gap segment:
--force-opacity-subtle(0.7) applied to the gap fill
Outline stroke
- Stroke color:
--force-color-chart-1through--force-color-chart-6at full opacity - Stroke width: 2px at
mdandlg; 1.5px atsm - Forecast projected portion: 40% opacity, dash
4px 4px - Stacked series patterns (3+ series): series 1 solid, series 2
4px 4px, series 32px 2px, series 46px 2px, series 56px 2px 2px 2px - Null gap segment:
--force-opacity-subtle(0.7), dash4px 4px
Background and structure
- Chart background:
--force-color-bg-surface - Gridlines:
--force-color-border-muted, 1px solid - Zero baseline:
--force-color-border-default, 1px solid - Crosshair:
--force-color-border-muted, 1px solid
Reference line
- Stroke:
--force-color-border-muted, 1px, dash2px 2px - Label:
--force-color-text-tertiary,--force-font-size-xs, right-aligned
Axis labels
- Tick label color:
--force-color-text-tertiary - Tick label size:
--force-font-size-xs(12px) - Axis title color:
--force-color-text-secondary - Axis title size:
--force-font-size-xs
Tooltip
- Background:
--force-color-bg-inverse - Text:
--force-color-text-on-inverse - Series swatch: 10px square using the series' chart color token (square to match the area fill shape)
- Cursor offset: ~12px
Interaction and states
- Dimmed (unfocused series):
--force-opacity-subtle(0.7) - Focus ring:
--force-shadow-focus-ring+--force-color-border-focus - Loading skeleton:
--force-color-bg-muted
Motion
- Draw-in on mount:
--force-duration-normal(250ms),--force-easing-standard - Stacked series reflow on legend toggle:
--force-duration-normal(250ms),--force-easing-standard - Data update transition:
--force-duration-normal(250ms),--force-easing-standard - Tooltip open:
--force-duration-fast(150ms),--force-easing-standard - Reduced motion override: all durations collapse to 0ms when
prefers-reduced-motion: reduce
Related components
| Component | Relationship | When to redirect |
|---|---|---|
| Line chart | Same shape, unfilled. | When the trajectory of the value is the primary question and the volume beneath it is not relevant. |
| Stacked bar | Categorical sibling. | When the x axis is discrete categories — products, regions, teams — and the reader is comparing composition per category. |
| Sparkline | Inline variant of this chart. | When the chart fits inside a table cell or KPI tile and only the trend shape is meaningful. Use via variant="sparkline". |
| KPI tile | Single-value fallback. | When only one data point exists or a single summary number is the takeaway. |
| Bar chart (grouped) | For data with negatives or discrete categories. | When any series contains negative values, or when the x axis is categorical. |