react-candlesticks
v0.7.14
Published
High-performance, composable candlestick charts for React.
Maintainers
Readme
React Candlesticks
Canvas-powered, JSX-composable candlestick charts for React, for trading UIs.
Build responsive trading charts in React with candlesticks, indicators, crosshairs, zoom, and theming — rendered on Canvas for smooth performance on large datasets.
react-candlesticks is in an early public release / soft launch phase. Feedback, bug reports, and edge-case reproductions are especially helpful.
Website • Documentation • npm • Live Demo
For bugs and feature requests, open an issue. For usage questions, start a discussion.
Installation
npm install react-candlesticksQuick Start
Paste this into your React app for a basic candlestick chart with volume:
import 'react-candlesticks/style.css';
import { Chart, Panel, Candlesticks, VolumeBars, exampleData }
from 'react-candlesticks';
export default function App() {
return (
<Chart
width={800}
height={500}
granularity="d1"
data={exampleData} // demo data
>
<Panel heightRatio={3}>
<Candlesticks />
</Panel>
<Panel>
<VolumeBars />
</Panel>
</Chart>
);
}granularity is optional if your dataset uses a consistent interval and you want the library to infer it automatically. For empty/loading states, pass granularity explicitly.
For a fuller walkthrough, see the Getting Started docs.
Why React Candlesticks?
- Composable like React — build charts using JSX (React components)
- Canvas rendering — predictable performance on large datasets
- Trading-focused — indicators, crosshairs, multi-panel layouts
- Nice feeling pan and zoom — mouse, mouse wheel, trackpad, touch
- Fully themeable — light and dark mode, or provide a custom theme
- Lightweight & dependency-free — no core dependencies (other than React and ReactDOM peer dependencies)
Usage Patterns
Declarative (JSX) ✅ recommended
The recommended approach for most use cases. Compose panels and layers declaratively using JSX.
import { Chart, Panel, Candlesticks, VolumeBars, BollingerBands, EMA, MACD, RSI }
from 'react-candlesticks';
<Chart granularity="d1" data={data}>
<Panel heightRatio={3}>
<Candlesticks />
<EMA period={50} />
<BollingerBands />
</Panel>
<Panel>
<VolumeBars />
</Panel>
<Panel>
<MACD />
</Panel>
<Panel>
<RSI />
</Panel>
</Chart>Config-driven (panels prop)
import { Chart } from 'react-candlesticks';
<Chart
granularity="d1"
data={data}
panels={[
{
heightRatio: 3,
layers: [
{ type: 'price:candlesticks' },
{ type: 'ema', period: 20 },
{ type: 'bollinger-bands' },
]
},
{
layers: [{ type: 'volume:bars' }]
},
{
layers: [{ type: 'macd' }]
},
{
layers: [{ type: 'rsi' }]
}
]}
/>Custom indicator layers
Use defineLayer to add an indicator implementation to a specific chart. A
definition controls config parsing, calculation, and Canvas drawing, and
provides a JSX component through its Component property.
import {
Candlesticks,
Chart,
Panel,
defineLayer,
drawLineSeries,
parseLineConfig,
} from 'react-candlesticks';
const doubleClose = defineLayer({
type: 'custom:double-close',
parseConfig: (config, _theme, panelId) => ({
...config,
id: config.id ?? `double-close_${panelId}`,
type: 'custom:double-close',
indicator: true,
// Share the candlestick price scale so doubled values use price coordinates.
defaultScale: { key: 'price_auto', domain: 'price', range: { type: 'auto' } },
scale: config.scale ?? null,
scalePolicy: 'derived',
requiredInputKeys: ['input'],
inputs: config.inputs ?? [
{ key: 'input', source: { type: 'price', field: 'close' } },
],
outputs: ['value'],
period: 1,
offset: 0,
lookback: 0,
calculate: true,
includeInAutoScale: true,
valueToY: (min, max, top, height) =>
value => top + ((max - value) / (max - min)) * height,
legend: null,
yAxis: null,
valueLabelFormatter: String,
}),
calculate: (_config, inputs, outputs, start, end) => {
for (let index = start; index < end; index++) {
outputs.value[index] = inputs.input.values[index] * 2;
}
},
draw: (
context, _axes, _chart, _panel, config, _layout, viewport,
_chartMetrics, _panelMetrics, layerMetrics,
) => {
const values =
viewport.layersData.layerDataInstances[config.id].outputValues.value;
const { intervalSize, scrollOffset } = viewport.timeScale.metadata;
drawLineSeries({
context,
values,
lineConfig: parseLineConfig({ color: '#8b5cf6', width: 2 })!,
valueToY: layerMetrics.valueToY,
startBarIndex: viewport.timeScale.startBarIndex,
endBarIndex: viewport.timeScale.endBarIndex,
intervalSize,
scrollOffset,
});
},
});
const DoubleClose = doubleClose.Component;
<Chart data={data} customLayers={[doubleClose]}>
<Panel>
<Candlesticks />
<DoubleClose />
</Panel>
</Chart>Custom type names must not collide with built-in or other custom layer types. Definitions are chart-scoped, so separate charts can use independent custom layer sets without global registration.
Minimal Mode for List/Thumbnail Charts
Use renderMode="minimal" when rendering many small charts per screen (for example, watchlist rows or card grids).
This mode defaults to a lighter configuration by disabling interaction and non-essential chart chrome unless you explicitly opt back in.
<Chart
renderMode="minimal"
pixelRatio={1}
width={120}
height={60}
data={data}
>
<Panel>
<Candlesticks yAxis={false} legend={false} />
</Panel>
</Chart>renderMode="minimal"defaultscrosshairs,grid,xAxis,borders,enableScroll, andenableZoomtofalse.- You can still override any of these explicitly.
pixelRatiodefaults to'device'; setpixelRatio={1}for cheaper rendering in dense lists.
Scale smoothing
Enable y-scale smoothing to reduce abrupt vertical rescaling while panning.
<Chart data={data} scaleSmoothing />
<Chart
data={data}
scaleSmoothing={{ durationMs: 240, expandImmediate: true }}
/>Imperative chart controls (experimental)
Use a ChartHandle ref when external UI needs to drive the viewport or crosshair.
import { useRef, useState } from 'react';
import type { ChartHandle, ChartViewport } from 'react-candlesticks';
import { Candlesticks, Chart, Panel, VolumeBars } from 'react-candlesticks';
function ControlledChart({ data }) {
const chartRef = useRef<ChartHandle>(null);
const [viewport, setViewport] = useState<ChartViewport | null>(null);
const highlighted = data[Math.floor(data.length * 0.7)];
return (
<>
<button
type="button"
onClick={() => chartRef.current?.setVisibleRange({
from: data.length - 120,
to: data.length - 40,
marginBars: 6,
})}
>
Show range
</button>
<button type="button" onClick={() => chartRef.current?.fitContent({ marginBars: 8 })}>
Fit
</button>
<button type="button" onClick={() => chartRef.current?.scrollToLatest({ marginBars: 8 })}>
Latest
</button>
<button
type="button"
onClick={() => chartRef.current?.setCrosshairPosition({
timestamp: highlighted.time,
value: highlighted.close,
panelId: 'price',
})}
>
Crosshair
</button>
<Chart
ref={chartRef}
data={data}
onViewportChange={setViewport}
userViewportCallbackMode="debounce"
userViewportCallbackDebounceMs={120}
>
<Panel id="price" heightRatio={3}>
<Candlesticks />
</Panel>
<Panel id="volume">
<VolumeBars />
</Panel>
</Chart>
{viewport && (
<output>
{viewport.startBarIndex}-{viewport.endBarIndex}
</output>
)}
</>
);
}setCrosshairPosition() gives pointer movement control again as soon as the user moves over the chart. Pass { lock: true } as the second argument to keep the programmatic crosshair fixed until clearCrosshairPosition() is called.
User-driven viewport callbacks default to one notification per animation frame. Use userViewportCallbackMode="debounce" for heavier React state updates, "sync" for every internal viewport update, or "none" when you only need imperative reads through getViewport().
Theming
Use the built-in 'light' or 'dark' theme, or provide a partial Theme object.
import type { Theme } from 'react-candlesticks';
// Named theme
<Chart theme="dark" ... />
const myCustomTheme: Theme = {
base: 'dark',
chart: {
backgroundColor: '#101820',
},
indicators: {
line: { width: 2 },
linePalette: ['#ffd166', '#5dd9c1', '#c77dff'],
},
layers: {
sma: {
series: {
value: { color: '#ffd166', width: 3 },
},
},
},
};
// Custom partial theme
<Chart theme={myCustomTheme} ... />See the Theme documentation for the full theme shape.
Compatibility and Limitations
- Supports React 18+ and React 19.
- Ships ESM only; CommonJS/UMD consumers are not supported.
- Intended for modern browser-based React apps.
- Chart rendering and interaction are client-side. In SSR frameworks, render the chart from a client component or client-only boundary.
- Runtime behavior depends on standard browser APIs including Canvas,
ResizeObserver,matchMedia,devicePixelRatio, and Pointer Events for touch and pinch interactions. - If you target older browsers or restricted webviews, you may need compatibility checks or polyfills for APIs such as
ResizeObserver. - Current chart time display defaults to
UTC. A public chart-level timezone configuration API is not exposed yet, so if your UI requires exchange-local or user-local time labels, treat that as a current limitation. - Mouse, trackpad, touch, and pinch interactions are covered in modern evergreen browsers. If you rely on embedded webviews, older Safari/WebKit builds, or custom kiosk environments, verify pointer and wheel behavior in your exact target runtime before rollout.
- Data should use a consistent interval if you want automatic
granularityinference. For irregular datasets, passgranularityexplicitly.
Layers
| Layer | Type string | Description |
|---|---|---|
| <Candlesticks> | 'price:candlesticks' | OHLC candlestick chart |
| <PriceLine> | 'price:line' | Line chart of a single price field |
| <VolumeBars> | 'volume:bars' | Volume bar chart |
| <ADX> | 'adx' | Average Directional Index |
| <ATR> | 'atr' | Average True Range |
| <BollingerBands> | 'bollinger-bands' | Bollinger Bands overlay |
| <CCI> | 'cci' | Commodity Channel Index |
| <EMA> | 'ema' | Exponential Moving Average |
| <MACD> | 'macd' | MACD oscillator |
| <OBV> | 'obv' | On-Balance Volume |
| <ParabolicSAR> | 'parabolic-sar' | Parabolic Stop and Reverse overlay |
| <RSI> | 'rsi' | Relative Strength Index |
| <SMA> | 'sma' | Simple Moving Average |
| <Stochastic> | 'stochastic' | Stochastic Oscillator |
| <WilliamsR> | 'williams-r' | Williams %R oscillator |
API Reference
Latest Articles
Lightweight Charts Alternative for React Trading Charts
Aug 11, 2026 · 12 min read · Guides
Compare Lightweight Charts and React Candlesticks by building the same React trading chart with candlesticks, SMA, volume, Stochastic, and toggleable chart layers.
react-candlesticks: Composable Candlestick Charts for React, Rendered on Canvas
30 July 2026 · 4 min read · Intro
An open-source React/TypeScript library for composable financial charts with candlesticks, volume, indicators, theming, custom layers, and drawings.
Use a React Candlestick Chart in Next.js
Jul 2, 2026 · 6 min read · Guides
Build an interactive React candlestick chart in Next.js with volume bars, SMA overlays, a Stochastic indicator, and light and dark themes.
Build a Crypto Price Chart in React
Jun 29, 2026 · 9 min read · Guides
Fetch free crypto OHLCV data and build a React crypto chart with granularity controls, chart type switching, volume, and removable indicators.
Build a React Candlestick Chart with Volume and Indicators
Jun 7, 2026 · 7 min read · Guides
Build an interactive OHLC chart with volume bars, technical indicators, crosshairs, zoom, and dark mode.
Project Notes
Prop Types
If you want runtime prop validation in a JavaScript app, install the optional peer dependency too:
npm install react-candlesticks prop-typesThen import Chart from the opt-in propTypes entrypoint:
import { Chart } from 'react-candlesticks/propTypes';
