Display trends over time with smooth curves and area fill options
Tags: chart trend time-series comparison
The LineChart component is ideal for visualizing trends and changes over time. It supports multiple series, smooth curved lines, data point markers, and can display filled areas under the lines.
Reporting props marked Svelte only (
valueFormat,showDataTable,exportable, reference lines, data zoom and so on) are available in@classic-homes/charts-svelte; React support is pending.
Import
<script>
import { LineChart } from '@classic-homes/charts-svelte';
</script>// React
import { LineChart } from '@classic-homes/charts-react';Basic Usage
<script>
import { LineChart } from '@classic-homes/charts-svelte';
const data = {
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'],
series: [
{ name: '2024', data: [120, 132, 101, 134, 90, 230] },
{ name: '2025', data: [220, 182, 191, 234, 290, 330] },
],
};
</script>
<LineChart title="Monthly Revenue" {data} smooth height={400} />Props
Chart-Specific Props
| Prop | Type | Default | Description |
|---|---|---|---|
data |
LineChartData |
required | Chart data with categories and series |
smooth |
boolean |
false |
Use smooth curved lines instead of straight segments |
areaFilled |
boolean |
false |
Fill the area under the line |
showDataPoints |
boolean |
false |
Show data point markers on the line |
stacked |
boolean | 'percent' |
false |
Stack multiple series on top of each other; 'percent' stacks each category's share of 100% (Svelte only) |
connectNulls |
boolean |
false |
Draw across missing (null) values instead of leaving a gap (Svelte only) |
showLabels |
boolean |
false |
Show data labels |
labelFormatter |
string | ((params: LabelFormatterParams) => string) |
- | Data label template or function |
xAxisConfig |
AxisConfig |
- | Horizontal axis name, tick formatter, rotation and range |
yAxisConfig |
AxisConfig |
- | Vertical axis name, tick formatter, rotation and range |
referenceLines |
ReferenceLine[] |
- | Lines marking targets or statistics: { value: number | 'average' | 'median' | 'min' | 'max', label?, series?, style?, color? } (Svelte only) |
referenceBands |
ReferenceBand[] |
- | Shaded value ranges: { from, to, label?, color?, series? } (Svelte only) |
dataZoom |
boolean | 'inside' | 'slider' |
- | Zoom and pan the category axis: 'inside' (wheel and drag), 'slider', or true for both (Svelte only) |
legend |
ChartLegendConfig |
- | Built-in legend position, alignment, icon and formatter |
onLegendChange |
(visible: Record<string, boolean>) => void |
- | Called when legend items are shown or hidden |
renderLegend |
Snippet<[LegendRenderProps]> |
- | Custom HTML legend (e.g. ChartLegend) instead of the built-in one; React takes a function returning a node |
onClick |
(params: DataPointEventParams) => void |
- | Callback when a data point is clicked |
onHover |
(params: DataPointEventParams) => void |
- | Callback when hovering over a data point |
Inherited Base Props
| Prop | Type | Default | Description |
|---|---|---|---|
title |
string |
required | Chart title for accessibility (aria-label) |
description |
string |
- | Optional description for screen readers |
height |
number | string |
400 |
Chart height in pixels or CSS value |
loading |
boolean |
false |
Show loading skeleton |
error |
string | null |
- | Error message to display |
theme |
'light' | 'dark' | 'auto' |
'auto' |
Theme preference |
animation |
boolean |
true |
Enable/disable animations |
showLegend |
boolean |
true |
Show chart legend |
showTooltip |
boolean |
true |
Show tooltip on hover |
showGrid |
boolean |
true |
Show grid lines |
class |
string |
- | Custom CSS class |
tooltipFormatter |
string | ((items: TooltipFormatterParams[]) => string) |
- | Custom tooltip template or HTML function |
tooltipValueFormatter |
(value: number) => string |
- | Format values in the default tooltip |
option |
EChartsOption |
- | Raw ECharts option deep-merged over the generated one |
minHeight |
number |
- | Minimum height in pixels; also bounds an 'auto' height |
maxHeight |
number |
- | Maximum height in pixels; also bounds an 'auto' height |
onRetry |
() => void |
- | Show a Retry button on the error state, calling this (Svelte only) |
emptyMessage |
string |
- | Message shown when data is empty |
valueFormat |
ValueFormatPreset | Intl.NumberFormatOptions | ((value: number) => string) |
- | How values are written in value axes, tooltips, labels and the data table: 'number', 'integer', 'compact', 'currency', 'currencyCents', 'percent', 'percentValue', 'days', Intl options or a function (Svelte only) |
locale |
string |
'en-US' |
Locale for valueFormat (Svelte only) |
onReady |
(chart: EChartsType) => void |
- | Called with the ECharts instance when it is created (Svelte only) |
events |
Record<string, (params) => void> |
- | Raw ECharts event handlers keyed by event name, e.g. datazoom (Svelte only) |
showDataTable |
boolean | 'sr-only' |
'sr-only' |
Render the data as a table: 'sr-only' for screen readers, true adds a visible "Show data" toggle, false for none (Svelte only) |
exportable |
boolean | ChartExportConfig |
false |
Show PNG and CSV download buttons; or { image, csv, filename } (Svelte only) |
patterns |
boolean |
false |
Fill series with decal patterns as well as colour, for colour-blind readers (Svelte only) |
Data Structure
interface LineChartData {
categories: string[]; // X-axis labels
series: Array<{
name: string; // Series name for legend
data: (number | null)[]; // Y-axis values; null leaves a gap
color?: string; // Optional custom color
labels?: (string | null)[]; // Optional per-point label text
stack?: string; // Stack group id; overrides `stacked` for this series
}>;
}Examples
Smooth Line Chart
<LineChart title="Monthly Sales" {data} smooth height={400} />With Data Points
<LineChart title="Monthly Sales" {data} smooth showDataPoints height={400} />Stacked Lines
<LineChart title="Stacked Revenue" {data} stacked smooth height={400} />With Area Fill
<LineChart title="Revenue Trend" {data} areaFilled smooth height={400} />Handling Click Events
<script>
function handleClick(params) {
console.log('Clicked:', params.seriesName, params.name, params.value);
}
</script>
<LineChart title="Interactive Chart" {data} onClick={handleClick} />Formatted Tooltip and Top Legend
<LineChart
title="Visitors"
{data}
legend={{ position: 'top', align: 'end' }}
tooltipValueFormatter={(v) => `${v.toLocaleString()} visits`}
/>Annotating Points
<LineChart
title="Visitors"
data={{
categories: ['Mon', 'Tue', 'Wed'],
series: [{ name: 'Visits', data: [120, 340, 180], labels: [null, 'Launch'] }],
}}
/>Missing Values
null leaves a gap in the line; connectNulls draws across it instead.
<LineChart
title="Weekly Sales"
data={{
categories: ['W1', 'W2', 'W3', 'W4', 'W5'],
series: [{ name: 'Sales', data: [12, 15, null, 18, 21] }],
}}
connectNulls
/>Value Formatting (Svelte only)
valueFormat formats the value axis, tooltip, data labels and data table in one go: a preset
('number', 'integer', 'compact', 'currency', 'currencyCents', 'percent',
'percentValue', 'days'), Intl.NumberFormatOptions, or a function. More specific
formatters (tooltipValueFormatter, labelFormatter, an axis formatter) win.
<LineChart title="Monthly Revenue" {data} valueFormat="currency" />
<LineChart
title="Monthly Revenue"
{data}
valueFormat={{ style: 'currency', currency: 'EUR' }}
locale="de-DE"
/>Reference Lines, Bands and Zoom (Svelte only)
<LineChart
title="Build Cycle Time"
{data}
valueFormat="days"
referenceLines={[
{ value: 'average', label: 'Average' },
{ value: 120, label: 'Target', style: 'solid' },
]}
referenceBands={[{ from: 100, to: 130, label: 'Goal range' }]}
dataZoom="slider"
/>Percent Stacking (Svelte only)
<LineChart title="Sales Mix" {data} stacked="percent" areaFilled />Data Table and Export (Svelte only)
Every chart renders its data as a screen-reader table by default (showDataTable="sr-only").
showDataTable adds a visible "Show data" toggle; exportable adds PNG and CSV downloads.
<LineChart title="Monthly Revenue" {data} showDataTable exportable={{ filename: 'revenue' }} />Time Axis
<LineChart
title="Daily Closings"
data={{
categories: ['2025-01-02', '2025-01-09', '2025-02-01'],
series: [{ name: 'Closings', data: [4, 7, 5] }],
}}
xAxisConfig={{ type: 'time' }}
/>Accessibility
- The
titleprop is used asaria-labelfor screen readers - Animations respect
prefers-reduced-motionmedia query - Keyboard navigation support for interactive elements
- High contrast colors in both light and dark modes