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.
The React edition (@gremorie/rx-data) renders with recharts inside the shadcn chart primitive; the Angular edition (@gremorie/ng-data) renders headless d3 geometry inside a styled SVG. The rendering engine differs; the public surface is identical input-for-input.
Anatomy
<line-chart>
└─ figure (role="img") card surface, aspect-video
├─ svg (chart frame)
│ ├─ cartesian grid
│ ├─ x axis (category from xKey)
│ ├─ y axis (numeric, optional via yAxis)
│ ├─ stroked lines, one per config key
│ └─ dots (optional via dots)
├─ tooltip overlay (optional via tooltip)
├─ legend (when config has >1 series)
└─ sr-only data tableThe React edition composes this surface through the shadcn chart primitive:
LineChart styled wrapper; one Line per config entry
└─ ChartContainer responsive frame; injects --color-<key> from config
├─ CartesianGrid horizontal rules
├─ XAxis category axis
├─ YAxis numeric axis (optional, yAxis)
├─ ChartTooltip hover card
│ └─ ChartTooltipContent token-styled tooltip body
└─ Line one per series; 2px stroke; optional dotsPreview
| month | Desktop | Mobile |
|---|---|---|
| Jan | 186 | 80 |
| Feb | 305 | 200 |
| Mar | 237 | 120 |
| Apr | 173 | 190 |
| May | 209 | 130 |
| Jun | 214 | 140 |
'use client';import { LineChart, type ChartConfig, type ChartDatum,} from '@gremorie/rx-data';const monthlyData: ChartDatum[] = [ { month: 'Jan', desktop: 186, mobile: 80 }, { month: 'Feb', desktop: 305, mobile: 200 }, { month: 'Mar', desktop: 237, mobile: 120 }, { month: 'Apr', desktop: 173, mobile: 190 }, { month: 'May', desktop: 209, mobile: 130 }, { month: 'Jun', desktop: 214, mobile: 140 },];const monthlyConfig: ChartConfig = { desktop: { label: 'Desktop', color: 'var(--chart-1)' }, mobile: { label: 'Mobile', color: 'var(--chart-2)' },};export function LineChartPreview() { return <LineChart data={monthlyData} config={monthlyConfig} xKey="month" />;}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" />;
}import { Component } from '@angular/core';
import { LineChart } from '@gremorie/ng-data';
import type { ChartConfig, ChartDatum } from '@gremorie/ng-data';
@Component({
selector: 'app-monthly-trend',
imports: [LineChart],
template: `<line-chart [data]="data" [config]="config" xKey="month" />`,
})
export class MonthlyTrendComponent {
readonly 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 },
];
readonly config: ChartConfig = {
desktop: { label: 'Desktop', color: 'var(--chart-1)' },
mobile: { label: 'Mobile', color: 'var(--chart-2)' },
};
}
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>).
| Prop | Type | Default | Description |
|---|---|---|---|
data | readonly 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. |
config | ChartConfig | - | 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>). |
xKey | string | - | Name of the category field on each row. Drives the X axis ticks. |
type | "natural" | "monotone" | "linear" | "step" | "natural" | Interpolation curve for the lines. |
dots | boolean | false | Render a marker at each data point. |
yAxis | boolean | true | Render the numeric Y axis. Set to false for a minimal, axis-free line (sparkline-style). |
tooltip | boolean | true | Show the hover tooltip. |
className | string | - | 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:
| Export | Role |
|---|---|
ChartContainer | Provides the chart context, the responsive frame, and injects --color-<key> CSS vars from config. |
ChartTooltip / ChartTooltipContent | Token-styled hover tooltip. |
ChartLegend / ChartLegendContent | Token-styled legend. |
useChart | Hook returning the active ChartConfig from context. |
Types
| Type | Shape |
|---|---|
ChartDatum | Record<string, string | number> & { fill?: string } - one row of chart data. |
ChartConfig | Record<string, { label?: ReactNode; color?: string }> - per-series label and color map. |
Composition
- Pick
xKeyfirst - the ordered category that runs along the bottom. - Author
configmapping each value field to a label and a token-driven color. Color tokens (--chart-1through--chart-5) already encode legible contrast across light and dark themes. - Pass
dataas an array of records. - 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
| month | Desktop |
|---|---|
| Jan | 186 |
| Feb | 305 |
| Mar | 237 |
| Apr | 173 |
| May | 209 |
| Jun | 214 |
<LineChart
data={data}
config={{ signups: { label: 'Sign-ups', color: 'var(--chart-1)' } }}
xKey="week"
/><line-chart [data]="data" [config]="config" xKey="week" />The default shape. Reach for a single line when the story is the trajectory of one metric.
Multi-series comparison
| month | Desktop | Mobile |
|---|---|---|
| Jan | 186 | 80 |
| Feb | 305 | 200 |
| Mar | 237 | 120 |
| Apr | 173 | 190 |
| May | 209 | 130 |
| Jun | 214 | 140 |
const config: ChartConfig = {
desktop: { label: 'Desktop', color: 'var(--chart-1)' },
mobile: { label: 'Mobile', color: 'var(--chart-2)' },
};
<LineChart data={data} config={config} xKey="month" />;<line-chart [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.
Dots
Set dots to render a marker at each data point. Reach for it when the data is sparse and you want each reading to be individually clickable / readable.
<LineChart data={data} config={config} xKey="month" dots /><line-chart [data]="data" [config]="config" xKey="month" [dots]="true" />Curve type
Set type to pick the interpolation curve - "natural" (default), "monotone", "linear" (straight segments), or "step" (stepped edges). Use "linear" to read exact slopes; use "step" for discrete state changes.
<LineChart data={data} config={config} xKey="month" type="monotone" />
<LineChart data={data} config={config} xKey="month" type="step" /><line-chart [data]="data" [config]="config" xKey="month" type="monotone" />
<line-chart [data]="data" [config]="config" xKey="month" type="step" />No axis
Set yAxis to false to drop the numeric axis for a minimal, sparkline-style line that leans on the tooltip for exact values.
<LineChart data={data} config={config} xKey="month" yAxis={false} /><line-chart [data]="data" [config]="config" xKey="month" [yAxis]="false" />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'
accessibilityLayeris enabled, providing keyboard navigation and screen-reader announcements for the data points. - Token contrast:
--chart-1through--chart-5are tuned for WCAG AA contrast against the card background in both light and dark themes. - Container element: the wrapper renders a
ChartContainerdiv 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
useDeferredValueboundary.
Related
- 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.