Skip to main content
Gremorie

Line Chart

Trend over an ordered domain, one stroke per series, color-tokened from chart variables.

Overview

LineChart is a recharts chart wired to Gremorie's design tokens through the shadcn chart primitive (ChartContainer) for trend lines over an ordered category. Pass tabular data, a serializable config that maps each value field to a label plus a color, and the xKey that names the category field. ChartContainer injects each series color as var(--color-<key>), and recharts renders the cartesian grid, axis ticks, and per-series stroked paths. Pass type to choose the interpolation curve or dots to mark each point.

Reach for LineChart when shape and direction are the headline - month-over-month conversion, weekly active users, deploys per day. Use AreaChart when the filled magnitude is the story; use BarChart for discrete category comparisons; use ScatterChart when the X axis is itself numeric and continuous.

Preview

Installation

bash npx gremorie@latest add rx-line-chart
bash pnpm dlx gremorie@latest add rx-line-chart
bash yarn dlx gremorie@latest add rx-line-chart

bash bunx --bun gremorie@latest add rx-line-chart

Usage

import { LineChart } from "@gremorie/rx-data";
import type { ChartConfig, ChartDatum } from "@gremorie/rx-data";

const data: ChartDatum[] = [
{ month: "Jan", desktop: 186, mobile: 80 },
{ month: "Feb", desktop: 305, mobile: 200 },
{ month: "Mar", desktop: 237, mobile: 120 },
{ month: "Apr", desktop: 73, mobile: 190 },
{ month: "May", desktop: 209, mobile: 130 },
{ month: "Jun", desktop: 214, mobile: 140 },
];

const config: ChartConfig = {
desktop: { label: "Desktop", color: "var(--chart-1)" },
mobile: { label: "Mobile", color: "var(--chart-2)" },
};

export function MonthlyTrend() {
  return <LineChart data={data} config={config} xKey="month" />;
}

Angular edition planned for a follow-up release; it mirrors this component's anatomy.

API

<LineChart>

The styled wrapper. Renders a ChartContainer div wrapping a recharts <LineChart> (with accessibilityLayer enabled): a cartesian grid, X axis, and one stroked <Line> per series in config, each stroked with var(--color-<key>).

PropTypeDefaultDescription
datareadonly ChartDatum[]-Tabular data. Each row maps string keys to numeric or category values. The column at xKey is the category; every key in config must exist on every row as a numeric value.
configChartConfig-Maps each series key to { label, color }. The color is any CSS color or token, typically "var(--chart-1)" through "var(--chart-5)"; ChartContainer exposes it as var(--color-<key>).
xKeystring-Name of the category field on each row. Drives the X axis ticks.
type"natural" | "monotone" | "linear" | "step""natural"Interpolation curve for the lines.
dotsbooleanfalseRender a marker at each data point.
tooltipbooleantrueShow the hover tooltip.
classNamestring-Merged onto the ChartContainer. Use for sizing escape hatches; the bundled style already supplies a rounded card surface plus aspect ratio.

Chart primitive exports

@gremorie/rx-data re-exports the shadcn chart primitive so you can compose custom charts. Wrap raw recharts (Line, Area, Bar, CartesianGrid, XAxis, YAxis) inside ChartContainer:

ExportRole
ChartContainerProvides the chart context, the responsive frame, and injects --color-<key> CSS vars from config.
ChartTooltip / ChartTooltipContentToken-styled hover tooltip.
ChartLegend / ChartLegendContentToken-styled legend.
useChartHook returning the active ChartConfig from context.

Types

TypeShape
ChartDatumRecord<string, string | number> & { fill?: string } - one row of chart data.
ChartConfigRecord<string, { label?: ReactNode; color?: string }> - per-series label and color map.

Composition

  1. Pick xKey first - the ordered category that runs along the bottom.
  2. Author config mapping each value field to a label and a token-driven color. Color tokens (--chart-1 through --chart-5) already encode legible contrast across light and dark themes.
  3. Pass data as an array of records.
  4. For custom layouts (different stroke widths, a custom legend, mixed series), compose raw recharts inside <ChartContainer> (see Composing with the chart primitive).

The chart auto-sizes to its parent via recharts' ResponsiveContainer, so the wrapping surface controls the width. The default class on the ChartContainer pins the chart to aspect-video for a stable card shape.

Variations

Single series

<LineChart
  data={data}
  config={{ signups: { label: 'Sign-ups', color: 'var(--chart-1)' } }}
  xKey="week"
/>

The default shape. Reach for a single line when the story is the trajectory of one metric.

Multi-series comparison

const config: ChartConfig = {
  desktop: { label: 'Desktop', color: 'var(--chart-1)' },
  mobile: { label: 'Mobile', color: 'var(--chart-2)' },
};

<LineChart data={data} config={config} xKey="month" />;

For shape-to-shape comparison across cohorts. Keep the count under five lines before a ScatterChart or small-multiples layout reads better.

Interpolation and dots

Set type to pick the interpolation curve ("natural", "monotone", "linear", or "step"), or dots to mark each data point:

<LineChart data={data} config={config} xKey="month" type="monotone" />
<LineChart data={data} config={config} xKey="month" dots />

Composing with the chart primitive

When you need full control, skip LineChart and compose raw recharts inside ChartContainer. The container still injects your token colors and tooltip styling.

import {
  ChartContainer,
  ChartTooltip,
  ChartTooltipContent,
} from '@gremorie/rx-data';
import { CartesianGrid, Line, LineChart, XAxis } from 'recharts';

<ChartContainer config={config}>
  <LineChart accessibilityLayer data={data} margin={{ left: 12, right: 12 }}>
    <CartesianGrid vertical={false} />
    <XAxis dataKey="month" tickLine={false} axisLine={false} tickMargin={8} />
    <ChartTooltip cursor={false} content={<ChartTooltipContent />} />
    <Line
      dataKey="desktop"
      type="natural"
      stroke="var(--color-desktop)"
      strokeWidth={2}
      dot={false}
    />
    <Line
      dataKey="mobile"
      type="natural"
      stroke="var(--color-mobile)"
      strokeWidth={2}
      dot={false}
    />
  </LineChart>
</ChartContainer>;

Compose raw recharts when you need thicker strokes, dashed segments, a reference line, or a custom legend. ChartContainer owns the responsive frame and the token color vars.

Accessibility

  • Accessibility layer: recharts' accessibilityLayer is enabled, providing keyboard navigation and screen-reader announcements for the data points.
  • Token contrast: --chart-1 through --chart-5 are tuned for WCAG AA contrast against the card background in both light and dark themes.
  • Container element: the wrapper renders a ChartContainer div with the series colors applied as CSS variables.
  • No streaming UI: charts do not implement a streaming append affordance. For live data, throttle parent updates or render inside a useDeferredValue boundary.
  • AreaChart - same axes, filled under the curve, when magnitude is the story.
  • BarChart - discrete categories instead of an ordered domain.
  • ScatterChart - independent X plus Y when the X axis is numeric.

On this page