A React data visualization library for charts, networks, and beyond.
Simple charts in 5 lines. Force-directed graphs, Sankey diagrams, treemaps, and chord diagrams when you need them. Full D3-level control when you want it.
import { LineChart } from "semiotic"
<LineChart
data={salesData}
xAccessor="month"
yAccessor="revenue"
/>Most React charting libraries give you bar charts, line charts, and pie charts. Semiotic gives you those too — but it's built for the projects where those aren't enough.
Network visualization. Show how things connect — org charts, dependency graphs, budget flows, taxonomies. Semiotic has force-directed graphs, Sankey diagrams, chord diagrams, tree layouts, treemaps, and circle packing as React components with the same prop API as LineChart.
Streaming data. Monitor live systems — server metrics, sensor feeds, financial tickers. Semiotic's realtime charts render on canvas at 60fps with a ref-based push API. Old data fades out (decay), new data flashes in (pulse), and stale feeds are flagged automatically.
Coordinated dashboards. Hover one chart, highlight matching data in
others. Brush a scatterplot, filter a bar chart. Semiotic's LinkedCharts
and ScatterplotMatrix provide crossfilter coordination that other libraries
leave you to build from scratch.
Statistical summaries. Box plots, violin plots, swarm plots, ridgeline plots, histograms — the distribution charts that data scientists need and most charting libraries skip. Add marginal distribution graphics (histogram, violin, ridgeline, boxplot) to scatterplot margins with a single prop.
| Layer | For | Example |
|---|---|---|
| Charts | Common visualizations with sensible defaults | <LineChart data={d} xAccessor="x" yAccessor="y" /> |
| Frames | Full control over rendering, interaction, and layout | <StreamXYFrame chartType="line" lineStyle={...} /> |
Every Chart component accepts a frameProps prop to access the underlying
Frame API without leaving the simpler interface.
Need a standard bar or line chart for a dashboard you'll never need to customize beyond colors and labels? Recharts has a larger ecosystem and more community examples. Need GPU-accelerated rendering for millions of data points? Apache ECharts handles that scale.
Semiotic is for projects that outgrow those libraries — when you need network graphs alongside time series, streaming data alongside static snapshots, or coordinated views across chart types.
| Library | Packed | Unpacked | What you get |
|---|---|---|---|
| Victory | 393 KB | 2.3 MB | Charts only |
| Lightweight Charts | 586 KB | 3.0 MB | Financial charts only |
| Semiotic | 668 KB | 2.5 MB | Charts + networks + streaming + coordination |
| Recharts | 1.4 MB | 6.4 MB | Charts only |
| Chart.js | 1.6 MB | 6.2 MB | Charts only, no React |
| ApexCharts | 1.8 MB | 8.4 MB | Charts only |
| ECharts | 11.4 MB | 57.6 MB | Everything, no React |
AI-ready. Semiotic ships with structured schemas (ai/schema.json), an
import from "semiotic/ai" entry point, and an MCP server — all designed for
LLM code generation. AI coding assistants can generate correct Semiotic code on
the first try. Run npx semiotic-ai --help for CLI options or add semiotic-mcp
to your MCP client config for tool-based chart rendering.
Vega-Lite compatible. Have existing Vega-Lite specs? fromVegaLite(spec)
translates them to Semiotic chart configs — instant onboarding from notebooks,
dashboards, or AI-generated specs. Composes with configToJSX(),
copyConfig(), and toURL() for full round-trip interop.
Streaming system models. Turn a streaming Sankey into a live system monitor:
click-to-inspect DetailsPanel, particle speed proportional to edge throughput,
threshold alerting with animated glow, and automatic topology diffing that
highlights new services as they appear. Visualization as product navigation.
npm install semiotic@3.0.0-beta.4Requires React 18.1 or later.
Hover one chart, highlight the same data in another — zero wiring:
import { LinkedCharts, Scatterplot, BarChart } from "semiotic"
<LinkedCharts>
<Scatterplot
data={data} xAccessor="age" yAccessor="income" colorBy="region"
linkedHover={{ name: "hl", fields: ["region"] }}
selection={{ name: "hl" }}
/>
<BarChart
data={summary} categoryAccessor="region" valueAccessor="total"
selection={{ name: "hl" }}
/>
</LinkedCharts>Live data fades old points, flashes new ones, flags stale feeds:
import { RealtimeLineChart } from "semiotic"
const chartRef = useRef()
chartRef.current.push({ time: Date.now(), value: cpuLoad })
<RealtimeLineChart
ref={chartRef}
timeAccessor="time"
valueAccessor="value"
decay={{ type: "exponential", halfLife: 100 }}
staleness={{ threshold: 5000, showBadge: true }}
/>Force-directed graphs and Sankey diagrams — same API as LineChart:
import { ForceDirectedGraph, SankeyDiagram } from "semiotic"
<ForceDirectedGraph
nodes={people} edges={friendships}
colorBy="team" nodeSize={8} showLabels
/>
<SankeyDiagram
edges={budgetFlows}
sourceAccessor="from" targetAccessor="to" valueAccessor="amount"
/>Live service topology with threshold alerting and click-to-inspect:
import { StreamNetworkFrame, ChartContainer, DetailsPanel, LinkedCharts } from "semiotic"
const chartRef = useRef()
chartRef.current.push({ source: "API", target: "Orders", value: 15 })
<LinkedCharts>
<ChartContainer title="System Monitor" status="live"
detailsPanel={
<DetailsPanel position="right" trigger="click">
{(datum) => <div>{datum.id}: {datum.value} req/s</div>}
</DetailsPanel>
}>
<StreamNetworkFrame ref={chartRef} chartType="sankey"
showParticles particleStyle={{ proportionalSpeed: true }}
thresholds={{ metric: n => n.value, warning: 100, critical: 250 }}
/>
</ChartContainer>
</LinkedCharts>Line, bar, scatter, area — all the basics, with sensible defaults:
import { LineChart, BarChart } from "semiotic"
<LineChart
data={salesData}
xAccessor="month" yAccessor="revenue"
curve="monotoneX" showPoints
/>
<BarChart
data={categoryData}
categoryAccessor="department" valueAccessor="sales"
orientation="horizontal" colorBy="region"
/>| Category | Components |
|---|---|
| XY | LineChart AreaChart StackedAreaChart Scatterplot BubbleChart Heatmap |
| Categorical | BarChart StackedBarChart GroupedBarChart SwarmPlot BoxPlot Histogram ViolinPlot DotPlot PieChart DonutChart |
| Network | ForceDirectedGraph ChordDiagram SankeyDiagram TreeDiagram Treemap CirclePack |
| Realtime | RealtimeLineChart RealtimeHistogram RealtimeSwarmChart RealtimeWaterfallChart RealtimeHeatmap |
| Coordination | LinkedCharts ScatterplotMatrix |
| Frames | StreamXYFrame StreamOrdinalFrame StreamNetworkFrame |
Paste a Vega-Lite spec, get a Semiotic chart:
import { fromVegaLite } from "semiotic/data"
import { configToJSX, fromConfig } from "semiotic"
const config = fromVegaLite({
mark: "bar",
data: { values: [{ a: "A", b: 28 }, { a: "B", b: 55 }] },
encoding: {
x: { field: "a", type: "nominal" },
y: { field: "b", type: "quantitative" },
},
})
// Render directly
const { componentName, props } = fromConfig(config)
// → componentName: "BarChart", props: { data, categoryAccessor: "a", valueAccessor: "b" }
// Or generate JSX code
configToJSX(config)
// → <BarChart data={[...]} categoryAccessor="a" valueAccessor="b" />Supports bar, line, area, point, rect, arc, tick marks with encoding translation for color, size, aggregation, and binning.
Import only what you need:
import { LineChart } from "semiotic/xy" // 123 KB
import { BarChart } from "semiotic/ordinal" // 118 KB
import { ForceDirectedGraph } from "semiotic/network" // 127 KB
import { LineChart } from "semiotic/ai" // HOC-only surface for AI generationGranular entry points export only v3 Stream Frames and HOC charts — no legacy utilities or backwards-compatibility shims.
Built with strict: true. Full type definitions ship with the package.
Generics for type-safe accessors:
interface Sale { month: number; revenue: number }
<LineChart<Sale>
data={sales}
xAccessor="month" // TS validates this is keyof Sale
yAccessor="revenue"
/>Static SVG generation for Node.js (email, OG images, PDF):
import { renderToStaticSVG } from "semiotic/server"
const svg = renderToStaticSVG("xy", {
lines: [{ coordinates: data }],
xAccessor: "date",
yAccessor: "value",
size: [600, 400],
})Works with Next.js App Router, Remix, and Astro via "use client" directives.
- Getting Started
- Charts — all 27 chart types with live examples
- Frames — full Frame API reference
- Features — axes, annotations, tooltips, styling, Vega-Lite translator
- Cookbook — advanced patterns and recipes
- Playground — interactive prop exploration
- Migration Guide — upgrading from v1.x or v2.x
- Changelog — full release history
See CONTRIBUTING.md. Our community follows the nteract Code of Conduct.
Development of this library owes a lot to Susie Lu, Jason Reid, James Womack, Matt Herman, Shelby Sturgis, and Tristan Reid.
The Sankey layout engine is based on sankey-plus
by Tom Shanley, which improved on his earlier
d3-sankey-circular with better cycle detection, hierarchical arc stacking,
and dynamic extent adjustment.
Semiotic icon based on an icon by Andre Schauer.
