Skip to content
quartiledocsv0.1
GitHub

AreaChart

PreviewSVGPublishes selection

Shows how one or more measures change over a continuous dimension, filled to the baseline. Stack series to read the total along the top edge and the parts below it.

Playground

Revenue by channel
Nov 2024 – Oct 2026 · monthly

Organic search from Nov 24 to Oct 26: up 87.8%, from $177.5K to $333.4K. Low $177.5K on Nov 24; high $389.4K on Jun 26. Paid social from Nov 24 to Oct 26: up 83.0%, from $127.1K to $232.6K. Low $126.7K on Dec 24; high $297.1K on Jun 26. Email from Nov 24 to Oct 26: up 80.7%, from $81.2K to $146.8K. Low $75.8K on Dec 24; high $186.4K on Jun 26. Direct from Nov 24 to Oct 26: up 72.2%, from $59.7K to $102.8K. Low $59.1K on Dec 24; high $133.8K on Jun 26. Total from Nov 24 to Oct 26: up 83.1%, from $445.5K to $815.7K. Low $445.5K on Dec 24; high $1.01M on Jun 26.

Monthly revenue by channel
MonthOrganic searchPaid socialEmailDirectTotal
Nov 24$177.5K$127.1K$81.2K$59.7K$445.5K
Dec 24$183.9K$126.7K$75.8K$59.1K$445.5K
Jan 25$188.5K$132.2K$84.0K$64.6K$469.3K
Feb 25$203.5K$149.7K$95.0K$65.7K$513.8K
Mar 25$222.1K$160.6K$103.2K$75.9K$561.7K
Apr 25$260.1K$175.7K$117.9K$86.6K$640.3K
May 25$276.4K$207.6K$130.9K$96.1K$711.0K
Jun 25$284.8K$211.0K$127.8K$91.9K$715.5K
Jul 25$299.7K$220.0K$128.6K$93.0K$741.2K
Aug 25$288.6K$196.6K$127.7K$94.3K$707.2K
Sep 25$273.4K$179.5K$123.7K$90.9K$667.5K
Oct 25$240.3K$164.1K$104.6K$84.5K$593.6K
Nov 25$230.4K$165.1K$101.4K$76.8K$573.7K
Dec 25$234.6K$154.9K$105.0K$71.9K$566.4K
Jan 26$237.7K$173.7K$114.6K$79.1K$605.0K
Feb 26$261.7K$184.4K$112.4K$90.0K$648.5K
Mar 26$316.1K$235.1K$140.9K$107.1K$799.3K
Apr 26$347.2K$263.0K$153.5K$112.5K$876.1K
May 26$387.1K$276.2K$164.7K$125.0K$953.0K
Jun 26$389.4K$297.1K$186.4K$133.8K$1.01M
Jul 26$389.0K$295.0K$179.8K$130.1K$993.8K
Aug 26$367.9K$269.4K$160.3K$131.2K$928.8K
Sep 26$342.4K$247.7K$151.5K$111.0K$852.6K
Oct 26$333.4K$232.6K$146.8K$102.8K$815.7K
curve
<AreaChart
  data={monthlyByChannel}
  x="month"
  y="revenue"
  color="channel"
  stack
  curve="monotone"
  xFormat="month"
  format="currency-compact"
/>

Installation

AreaChart is exported from @quartile/react, alongside every other chart and component.

git clone https://github.com/zinnoberHaus/quartile

Not on npm yet: build the package from the clone as described in Installation. The preview API may change before publication.

Usage

Pass rows and name the fields. Types, formats and axis labels come from the data's schema; see Data model.

import { AreaChart } from '@quartile/react';

// rows: { month: '2026-10-01', channel: 'Email', revenue: 104200 }, …
type RevenueRow = { month: string; channel: string; revenue: number };

export function RevenueByChannel({ rows }: { rows: RevenueRow[] }) {
  return (
    <AreaChart data={rows} x="month" y="revenue" color="channel" stack xFormat="month" />
  );
}
With brush, dragging across the plot publishes a between range on x to the nearest <Selection>. The chart filters itself by every other predicate. With two or more series, the legend doubles as a series filter. See Linked selections.

Props

PropTypeDefaultDescription
datarequiredDataInput<R>—Rows to plot, or a dataset with a schema attached.
xrequiredkeyof R & string—Field for the horizontal axis. Dates and numbers are placed on a continuous scale.
yrequired(keyof R & string) | (keyof R & string)[]—One or more measures. Pass an array for multiple series.
colorkeyof R & string—Splits rows into series by a categorical field. Rows sharing an x and series are summed.
stackbooleanfalseStacks series on top of each other, so the top edge is the total.
curve'linear' | 'monotone' | 'step'Curve'monotone'Interpolation between points. Monotone never overshoots the data.
formatFormatter—Formats the y axis and tooltip values. Defaults to the field's schema format.
xFormatFormatter—Formats the x axis. Defaults to the field's schema format.
legendboolean—Shows a legend under the plot that doubles as a series filter. Defaults to true for 2+ series.
colorsstring[] | Record<string, string>—Series colors, by index or by series key. Defaults to the categorical palette in order.
brushbooleanfalseLets readers drag to select a range of x and publishes it to the nearest Selection.
annotations{ x: unknown; label: string }[]—Vertical markers with a short label.
idstring—Publisher id for the selection. Defaults to a generated id.
selectionstring | false—Selection to read from and publish to. Defaults to the nearest; false opts out.
onSelect(predicate: Predicate | null) => void—Called when a brush or keyboard selection changes.
Frame and state props shared with the charts (11) · ChartBaseProps, ChartStateProps
PropTypeDefaultDescription
heightnumber240Plot height in px. Width always fills the container.
classNamestring——
styleCSSProperties——
aria-labelstring—Accessible name. A summary of the data is generated and rendered as hidden text inside the figure.
view'chart' | 'table'—table renders the same data as a table, with the same formats, at the chart's size. Large lazy tables expose a data-view control rather than mounting every hidden row.
tooltipNotestring—Plain-text context shown with tooltips and included in the accessible chart description.
loadingboolean | string—Shows the loading state at the chart's size, so the layout never jumps.
errorboolean | string | Error | null—Shows the error state. A string or Error becomes the message.
errorCodestring—Shown in the error state; copyable for support.
onRetry() => void——
empty{ title?: string; description?: string; action?: ReactNode }—Title and description for the empty state. Shown when there are no rows.

Accessibility

Keyboard
Tab into the plot, ← → between x values, Home and End to jump. With brush, Enter or Space selects the focused x value. Escape clears the cursor.
Screen readers
An auto-written summary per series (range, trend, low and high) as hidden text inside the figure. The focused x value is announced as you move.
Table fallback
Screen readers always get a table of the plotted values with the same formats. view="table" shows it at the chart's size.
Report an issueBuilt Oct 21, 2026