https://github.com/brandtnewlabs/react-native-livechart
High-performance live line & candlestick charts for React Native, built on Skia and Reanimated.
https://github.com/brandtnewlabs/react-native-livechart
candlestick chart charts expo gesture-handler react-native reanimated skia trading typescript
Last synced: about 1 month ago
JSON representation
High-performance live line & candlestick charts for React Native, built on Skia and Reanimated.
- Host: GitHub
- URL: https://github.com/brandtnewlabs/react-native-livechart
- Owner: brandtnewlabs
- License: other
- Created: 2026-04-03T08:10:06.000Z (3 months ago)
- Default Branch: main
- Last Pushed: 2026-06-05T18:19:53.000Z (about 1 month ago)
- Last Synced: 2026-06-05T19:19:15.156Z (about 1 month ago)
- Topics: candlestick, chart, charts, expo, gesture-handler, react-native, reanimated, skia, trading, typescript
- Language: TypeScript
- Homepage: https://react-native-livechart.brandtnewlabs.com
- Size: 539 KB
- Stars: 7
- Watchers: 1
- Forks: 0
- Open Issues: 4
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- Funding: .github/FUNDING.yml
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
- Security: SECURITY.md
- Agents: AGENTS.md
Awesome Lists containing this project
README
# react-native-livechart
[](https://www.npmjs.com/package/react-native-livechart)
[](https://github.com/brandtnewlabs/react-native-livechart/actions/workflows/test.yml)
[](https://github.com/brandtnewlabs/react-native-livechart/blob/main/LICENSE)
[](https://react-native-livechart.brandtnewlabs.com)
High-performance **live** line and candlestick charts for React Native, built on **[@shopify/react-native-skia](https://shopify.github.io/react-native-skia/)**, **[react-native-reanimated](https://docs.swmansion.com/react-native-reanimated/)**, and **[react-native-gesture-handler](https://docs.swmansion.com/react-native-gesture-handler/)**. Data and live values flow through Reanimated `SharedValue`s, so the UI thread animates without per-frame JS bridge traffic.
π **[Documentation β](https://react-native-livechart.brandtnewlabs.com)**
π€ **Docs MCP** β point an AI assistant (Claude, Cursor, β¦) at the docs via the hosted MCP server: `https://react-native-livechart.brandtnewlabs.com/mcp`
βΆ Watch the full video demos in the docs β
> The design, feature set, and API shape are **conceptually inspired by [liveline](https://github.com/benjitaylor/liveline)** β Benji Taylor's real-time canvas chart for React β reimagined for React Native. This is **not** a fork; see [Acknowledgments](#acknowledgments).
## Features
- π **Line & candlestick** modes (with line/candle morph) in a single component
- 𧬠**Multi-series** charts with a toggleable legend and per-series live dots
- π **Scrubbing** with a crosshair and worklet-friendly `onScrub` payloads
- β‘ **Momentum** detection and **degen** effects (particle bursts + shake on big swings)
- π·οΈ **Trade markers** driven by a `SharedValue` trade stream
- π¨ **Theming** with light/dark modes, an accent-driven `palette`, and `metrics` sizing/motion tokens
- β³ **Loading** (breathing-line shell) and **paused** states out of the box
- π§΅ **SharedValue-driven** rendering β history and live values stay on the UI thread
## Demos
See every feature in motion β line & area, candlestick, multi-series, scrubbing, momentum & degen, markers, theming, and more β in the **[documentation](https://react-native-livechart.brandtnewlabs.com)**.
## Install
```bash
npm install react-native-livechart
```
### Peer dependencies
Install the library's **peer dependencies** in your app (versions should match your React Native / Expo SDK):
| Peer | Role |
| ------------------------------ | ----------------------------------- |
| `react` | UI |
| `react-native` | Host |
| `@shopify/react-native-skia` | Canvas rendering |
| `react-native-reanimated` | Shared values, animations, worklets |
| `react-native-worklets` | Required by Reanimated 4+ |
| `react-native-gesture-handler` | Pan / scrub gestures |
Follow the Skia, Reanimated, and Gesture Handler install docs for your toolchain (Babel plugin, `GestureHandlerRootView`, etc.).
### Babel (required)
The package ships **TypeScript source**; your app's bundler compiles it with the same stack as a typical **Expo / Reanimated 4** project. In practice that means:
- **`babel-preset-expo`** (or an equivalent that includes Reanimated's Babel plugin), and
- **`react-native-worklets/plugin`** β keep it **last** in the `plugins` array, matching this repo's root [`babel.config.js`](https://github.com/brandtnewlabs/react-native-livechart/blob/main/babel.config.js).
If you omit Worklets or reorder plugins, worklets in the chart may fail at build or runtime.
### Metro / `package.json` exports
From **Expo SDK 53+**, Metro resolves `import` using `package.json` **`exports`**, including the **`react-native`** condition (see [Expo Metro: ES Module resolution](https://docs.expo.dev/versions/latest/config/metro/#es-module-resolution)). This library's runtime entry is **`src/index.ts`** under that condition. If you disabled package exports (`unstable_enablePackageExports: false`), align your resolver or re-enable exports so resolution matches the published map.
## Quick start
```tsx
import { useEffect } from "react";
import { View } from "react-native";
import { useSharedValue } from "react-native-reanimated";
import { LiveChart, type LiveChartPoint } from "react-native-livechart";
function LivePrice() {
const data = useSharedValue([]);
const value = useSharedValue(100);
useEffect(() => {
const id = setInterval(() => {
const next = value.get() + (Math.random() - 0.5) * 2;
// Reanimated 4: append in place on the UI thread + set the scalar β never `data.value = ...`
data.modify((arr) => {
"worklet";
arr.push({ time: Date.now() / 1000, value: next });
if (arr.length > 600) arr.shift();
return arr;
});
value.set(next);
}, 100);
return () => clearInterval(id);
}, [data, value]);
return (
);
}
```
Candlestick mode is a prop away:
```tsx
```
Multi-series with a legend:
```tsx
import { LiveChartSeries, type SeriesConfig } from "react-native-livechart";
const series = useSharedValue([
{ id: "btc", label: "BTC", color: "#f7931a", data: [], value: 0 },
{ id: "eth", label: "ETH", color: "#627eea", data: [], value: 0 },
]);
;
```
## API overview
The tables below are a **highlight** β the **canonical, full reference is the TypeScript types and JSDoc** shipped in the source (your editor surfaces them on hover and autocomplete).
### `LiveChart` (single series)
| Prop | Description |
| ---------------------------------------- | ------------------------------------------------------------------- |
| `data` | `SharedValue` β history |
| `value` | `SharedValue` β live value for interpolation |
| `theme` | `"light"` or `"dark"` |
| `accentColor` | Primary accent; palette is derived from it |
| `timeWindow` | Visible window in seconds (default `30`) |
| `paused` | Freeze scrolling |
| `loading` | Breathing-line shell until data is ready |
| `mode` | `"line"` (default) or `"candle"` |
| `candles` / `liveCandle` / `candleWidth` | Candlestick mode |
| `tradeStream` | `SharedValue` for trade markers |
| `degen` | Particle burst + shake on momentum swings |
| `scrub` | Crosshair scrubbing |
| `momentum` | `true` / `false` / `"up"`, `"down"`, or `"flat"` / `MomentumConfig` |
| `dot` | `true` / `false` (hide) / `DotConfig` β `radius`, `ring` (halo), `color` |
| `metrics` | Sizing & motion tokens β geometry/feel analogue of `palette` |
| `onScrub` | Callback: `ScrubPoint` or `null` |
### `LiveChartSeries` (multi-series)
| Prop | Description |
| ---------------- | ------------------------------------------- |
| `series` | `SharedValue` |
| `legend` | Toggle chips / compact legend |
| `dot` | `true` / `false` (hide) / `MultiSeriesDotConfig` β haloed `ring`, `color`, `radius`, `pulse`, `valueLine`, `valueLabel` |
| `scrub` | Crosshair scrubbing (**on by default** as of v2) |
| `onSeriesToggle` | Chip tap |
| `onScrub` | Worklet-friendly multi-series scrub payload |
These tables are a **highlight, not the full surface** (`LiveChart` alone has ~48 props). Other shared props include `font`, `insets`, `smoothing`, `xAxis`, `yAxis`, `referenceLines`, `gridStyle`, `palette`, `metrics`, `markers`, `leftEdgeFade`, `line`, `formatValue`, `formatTime`, and `emptyText`; single-series adds `gradient`, `badge`, `pulse`, `valueLine`, and `showValue`. Every overlay toggle follows the same **`boolean | Config`** convention (`badge`, `gradient`, `pulse`, `valueLine`, `scrub`, `yAxis`, `xAxis`, `leftEdgeFade`, `legend`, and `dot`) β pass `true`/omit for defaults, `false` to disable, or an object to customize. Both charts share the same `dot` styling (a `DotConfig` base β `radius`, `ring`, `color`); multi-series extends it with `pulse`, `valueLine`, and `valueLabel`. Beyond `palette` (color), `metrics` exposes sizing & motion tokens (badge/candle geometry, grid/motion speeds) with the same per-key override model. See the TypeScript types and JSDoc for the complete, canonical reference.
## Migrating to v2
v2 makes the feature-flag surface uniform and adds the `metrics` token object. Two behavior changes to know about:
- **`LiveChartSeries` scrubs by default.** Crosshair scrubbing is now on by default (it previously defaulted off), matching `LiveChart`. Pass `scrub={false}` to restore the old behavior.
- **`dot.show` is deprecated.** Prefer `dot={false}` to hide the live dot β every overlay toggle now follows the same `boolean | Config` convention. `dot={{ show: false }}` still works.
Everything else is additive: the new [`metrics`](https://react-native-livechart.brandtnewlabs.com/guides/theming#sizing-and-motion-tokens) prop is optional, and omitting it keeps the built-in geometry and motion.
## Examples (Expo app in this repo)
Run the example from the repository root:
```bash
npm install
npm start
```
The example app bundles the library from **`src/`**; Metro's [`watchFolders`](https://github.com/brandtnewlabs/react-native-livechart/blob/main/metro.config.js) include the package so Fast Refresh sees edits without a separate library bundler. Optionally run **`npm run build:lib:types:watch`** if you want **`dist/*.d.ts`** regenerated continuously for editor/tsconfig consumers.
Screens demonstrate candlestick mode, multi-series, scrub, momentum tuning, degen mode, loading / paused states, and more.
## How it works
- **Skia** draws grid, line, candles, badges, and overlays on the GPU.
- **Reanimated** owns timeline layout, smoothing, and scrub state; hooks feed a small engine API on the UI thread.
- **Gesture Handler** drives scrubbing and chart interactions.
A frame-callback engine (`useFrameCallback`) runs a pure tick function on the UI thread each frame, updating display range, time window, and smoothed values, then writing results to `SharedValue`s. Path builders and overlays read those `SharedValue`s inside `useDerivedValue`, so React re-renders stay minimal.
## Contributing
Contributions are welcome β see [CONTRIBUTING.md](https://github.com/brandtnewlabs/react-native-livechart/blob/main/CONTRIBUTING.md) for the dev setup, the `npm run verify` gate, and the worklets-plugin rule. By participating you agree to the [Code of Conduct](https://github.com/brandtnewlabs/react-native-livechart/blob/main/CODE_OF_CONDUCT.md).
## Acknowledgments
**[liveline](https://github.com/benjitaylor/liveline)** by **Benji Taylor** (MIT) is the **primary inspiration** for this project: live updating charts, line and candlestick modes (including line/candle morph ideas), multi-series behavior, momentum and degen effects, scrubbing, loading and paused states, theme plus accent-driven palettes, and the overall prop vocabulary β even though names differ here (for example `accentColor` vs `color`, `timeWindow` vs `window`, and `SharedValue` streams instead of React state).
This package is a **React Native reimplementation** using **Skia**, **Reanimated**, and **Gesture Handler**. It is **not** the web canvas component ported line-for-line. The codebase **diverged** over time toward more hooks, layout options, and customizability for mobile.
**Third-party / adapted code:** math utilities used for chart geometry and smoothing (including FritschβCarlson monotone spline tangents, momentum detection, range/lerp helpers, and related pieces) are **adapted from liveline** under the MIT license. See the [LICENSE](https://github.com/brandtnewlabs/react-native-livechart/blob/main/LICENSE) file for the formal notice.
### Compared to liveline
- **Rendering:** liveline uses a DOM `` and `requestAnimationFrame`; this library uses **Skia** on the UI thread.
- **Data flow:** liveline takes plain `data` / `value` props; here history and live values are **`SharedValue`s** so worklets avoid per-frame JS bridge work.
- **Input:** scrubbing uses **pan gestures** instead of canvas hover.
- **Scope:** liveline includes features this repo does not (for example **orderbook** visualization and built-in time-window controls); this repo adds **React Nativeβspecific** pieces (for example trade markers via `tradeStream`) and a more decomposed hook API.
## License
MIT β see [LICENSE](https://github.com/brandtnewlabs/react-native-livechart/blob/main/LICENSE).