Svelte 5 plots for data storytelling, built on svelteplot. A plot is one graph - axes and marks - that carries its own title, legend, tooltip, facets and timeline, so a finished, readable figure is one component with a handful of props.
It aims for a sweet spot between the flexibility of d3, the declarative spirit of the grammar of graphics (data mapped to channels, scales and marks) and the convenience of a classic plotting library, where each plot kind is a first-class component.
<script lang="ts">
import { LinePlot } from '@fundar/data-chart-telling';
import { REGION_VALUES } from './datasets';
</script>
<!-- One line per region, with a title, the automatic legend, end-of-line values and a tooltip. -->
<LinePlot
width={720}
height={400}
title="Monthly inflation by region (%)"
data={REGION_VALUES}
x="date"
y="value"
color="region"
tooltip
scales={{ x: { label: false } }}
styles={{ values: { show: true } }}
/>Every Svelte snippet in this README is a runnable file in examples/, and the data comes from examples/datasets/.
Every plot kind shares one vocabulary: the same channels (x, y, color, grouping, opacity, symbol, r), the same scales, styles, segments, markers, transforms, tooltip, legend, timeline and facet props, and one global theme.
pnpm add @fundar/data-chart-telling svelte svelteplot
# only for GeoPlot fed with TopoJSON
pnpm add topojson-clientThe package ships Svelte components, so the app needs the Svelte compiler (@sveltejs/vite-plugin-svelte or SvelteKit). Types ship with it.
timeline slices the rows by a field and steps through them. It draws as a player by default: play and pause, the current step and a slider, in the figure's chrome.
<script lang="ts">
import { BarPlot } from '@fundar/data-chart-telling';
import { REGION_VALUES } from './datasets';
</script>
<!--
`timeline` slices the rows by `accessor`. A timeline is a player by default:
play/pause, the current step and a slider in the chrome. `progress` sets where
it starts. `type: 'rule'` draws a guide beside the plot with no controls
instead (see TimelineRule). To build your own widget, read
`useFigure().timeline` (seek, play, pause, next, ...).
-->
<BarPlot
width={720}
height={400}
data={REGION_VALUES}
x="region"
y="value"
scales={{ y: { domain: [0, 30] } }}
timeline={{ accessor: 'date', progress: 0.25, player: { autoplay: false, loop: true } }}
/>type: 'rule' draws a rule beside the plot instead, a line with the steps written along it. The page drives it through progress (0 to 1), from a slider, scroll position or anything else.
<script lang="ts">
import { LinePlot } from '@fundar/data-chart-telling';
import { REGION_VALUES } from './datasets';
// A rule has no controls of its own: the page moves it through `progress` (0 to 1).
// One step per year; a line plot shows every row up to the current step.
let progress = $state(0.5);
</script>
<input type="range" min="0" max="1" step="0.001" bind:value={progress} />
<LinePlot
width={720}
height={400}
data={REGION_VALUES}
x="date"
y="value"
color="region"
timeline={{ accessor: (row) => row.date.getUTCFullYear(), type: 'rule', progress }}
/>See Timeline for both in detail.
Start with the concepts; the rest is organised by what you want a plot to do.
| Topic | What it covers |
|---|---|
| Getting started | Installing, a first plot, sizing a plot to its container, loading data |
| Concepts | Plots and figures, rows and series, channels, the props every plot shares |
| Plots | Every plot kind: what it draws and what it needs |
| Scales | Axes (x, y) and channel scales (color, grouping, opacity, symbol, r, length) |
| Styles and segments | Value labels, frames, gap filling, and styling ranges of the data |
| Markers | Extra marks on a plot: annotations, regions, hover highlights, custom components |
| Transforms and statistics | Stacking, binning, smoothing, regression and the other data transforms |
| Tooltip and hover | Floating tooltips, in-plot highlights, syncing hover across plots |
| Legend | The automatic legend, toggling series, custom sections |
| Timeline | Stepping through the data by time, with a player bar (default) or a rule |
| Chrome | Title, subtitle, caption, header, footer, dividers and their order |
| Facets | Small multiples: grids, carousels, pages |
| Composer | Several plots in one figure, with shared hover, legend and timeline |
| Reading plot state | usePlot and useFigure, to build custom UI around a plot |
| Maps | GeoPlot: data, projections, choropleths, camera and map markers |
| Theming | The global configuration, themes, locale and CSS variables |
| Architecture | How a plot is assembled, for contributors |
| Development | Building, testing, Storybook and publishing |
Working examples live in examples/; the online Storybook (or pnpm storybook locally) shows every option live.
llms.txt is the index and llms-full.txt is a single-file guide with the rules that matter most. Both ship inside the npm package, next to the runnable examples/.
MIT. Keep the copyright notice and license text in copies of the code.



