> ## Documentation Index
> Fetch the complete documentation index at: https://react-native-livechart.brandtnewlabs.com/llms.txt
> Use this file to discover all available pages before exploring further.

# LiveChartSeries

> Props for the multi-series line component.

```tsx theme={null}
import { LiveChartSeries } from "react-native-livechart";
```

`LiveChartSeries` draws several line series sharing an axis, time window, and crosshair. It
accepts all the shared theming, axis, range, layout, and text props from
[`LiveChart`](/api-reference/livechart) (`theme`, `accentColor`, `palette`, `metrics`, `font`,
`canvasMode`, `timeWindow`, `smoothing`, `rangeAnimation`, [`snapKey`](/api-reference/livechart#param-snap-key),
[`yRangeScale`](/guides/y-range-scale), `line`, `yAxis`,
`referenceLines`, `formatValue`, …), plus the multi-series props below.

The inherited `yAxis.intervalScale` chooses dynamic nice intervals in display units without
changing any series values. Pair it with a `formatValue` that applies the same multiplier. If the
scaled live range cannot be represented, interval selection safely falls back to source units.

On Android, the shared experimental `canvasMode="opaque"` option selects an opaque SurfaceView and
paints the palette background inside the canvas. See
[Android surface rendering](/guides/android-surface-rendering) for constraints and profiling guidance.

`yAxis={{ side: "left" }}` also places multi-series Y-axis labels in the gutter
reserved by `insets.left`; right-side series value labels remain unchanged.

## Series opacity

<ParamField body="seriesOpacity" type="SharedValue<number>" default="1">
  A UI-thread opacity multiplier for every plotted series. Set it to `0.5`
  while replacement history loads, then restore it to `1` when the new data
  arrives. It dims strokes, value lines, and inline value labels without
  affecting axes, the legend, reference lines, or scrub UI. Live dots and pulse
  rings fade completely out while the multiplier is below `1`, then fade back in
  once it returns to `1`, avoiding translucent dots over their own strokes. See
  [Dimming replacement data](/guides/multi-series#dimming-replacement-data).
</ParamField>

## Manual Y-range scaling

<ParamField body="rangeAnimation" type="RangeAnimationConfig">
  Ease the shared fitted Y-range independently of series-tip and time-window
  smoothing. `animateExpansion: true` opts into outward easing;
  `expansionSmoothing` and `contractionSmoothing` override each direction's
  per-60fps-frame speed (0..1). Omitted speeds inherit `smoothing`. Omission of
  the config preserves instant expansion and eased contraction. `smoothing: 1`,
  explicit `snapKey` changes, and active `yRangeScale` dragging remain immediate.
  While the fitted and displayed ranges do not overlap, contraction is limited
  to the animated expansion speed so the bounds cannot cross.
  Custom overlays keep following the animated `ChartOverlayContext.scale`.
  See [Y-range animation](/guides/y-range-scale#animating-automatic-range-changes)
  for a hold/release example without a return timer.
</ParamField>

<ParamField body="yRangeScale" type="SharedValue<number>" default="1">
  Multiplies the shared fitted Y-range around its midpoint. Drive it from a
  price-gutter gesture to stretch or compress every visible series together;
  hidden series remain excluded from the underlying fit. Values must be positive
  and finite, and invalid values safely behave as `1`. With the inherited
  `nonNegative` prop, zoom-out stops at the zero floor. Read on the UI thread
  each frame. **@experimental.** See
  [Manual Y-range scaling](/guides/y-range-scale).
</ParamField>

## Custom overlays

<ParamField body="renderOverlay" type="(ctx: ChartOverlayContext) => ReactElement | null">
  Render a full-bleed custom React Native overlay with the live price↔pixel /
  time↔pixel bridge. [`ChartOverlayContext`](/api-reference/types#chartoverlaycontext)
  includes the resolved plot rectangle, so custom off-axis tags and connectors can
  stop at the same axis inset as the chart. Return `null` or `undefined` for no
  overlay. See [Overlay bridge](/guides/overlay-bridge).
</ParamField>

## Reference-line tags

<ParamField body="renderReferenceLine" type="(ctx: ReferenceLineRenderProps) => ReactElement | null">
  Replace a Form-A reference line's built-in Skia badge or gutter label with any
  React Native element. Return `null` or `undefined` for per-line fallback to the
  built-in tag. The custom view tracks the line's live Y position, pins to the
  nearest plot edge when off-axis, and respects left, center, and right badge
  positions. A left- or right-pinned badge keeps its dashed connector, beginning
  after the measured custom view. The reference-line stroke remains visible. See
  [Reference lines and bands](/guides/reference-lines-and-bands#custom-tags-renderreferenceline).
</ParamField>

<ParamField body="renderOffAxisReferenceLine" type="(ctx: ReferenceLineRenderProps) => ReactElement | null">
  Replace only an off-axis Form-A tag. The standard Skia tag or gutter label stays
  in range, while the custom React Native view takes over when the line is pinned
  above or below the plot. A left- or right-pinned `badge` (or legacy
  `offAxisBadge`) retains its dashed connector from the custom view's measured
  edge. Return `null` for lines that opt out, and use `ctx.edge` inside the
  returned component for a directional caret. See
  [Reference lines and bands](/guides/reference-lines-and-bands#off-axis-only-custom-tags-renderoffaxisreferenceline).
</ParamField>

## Series data

<ParamField body="series" type="SharedValue<SeriesConfig[]>" required>
  Array of series definitions. Read on the UI thread. Each series can override
  the shared `line.simplify` screen-space tolerance with `simplify`; `0` disables
  simplification for that series. See [Line denoising](/guides/line-denoising)
  and [`SeriesConfig`](/api-reference/types).
</ParamField>

## Axis labels

Shared with [`LiveChart`](/api-reference/livechart#axes-grid-range). Both
default off.

<ParamField body="topLabel" type="boolean | AxisLabelConfig" default="false">
  Edge label at the plot's top. `true` shows the built-in value label — the
  chart's current top Y-axis bound, updated each frame. Pass
  [`AxisLabelConfig`](/api-reference/types#axislabelconfig) (`format` / `color` /
  `position`) or `{ render }` for a custom element.
</ParamField>

<ParamField body="bottomLabel" type="boolean | AxisLabelConfig" default="false">
  Edge label at the plot's bottom (the current bottom Y-axis bound), with the
  same options as `topLabel`.
</ParamField>

## Legend

<ParamField body="legend" type="boolean | LegendConfig" default="true">
  Toggle chips. Configure `position`, `compact`, and `style`.
</ParamField>

<ParamField body="onSeriesToggle" type="(id: string, visible: boolean) => void">
  Fires when a legend chip is tapped.
</ParamField>

## Dots

<ParamField body="dot" type="boolean | MultiSeriesDotConfig" default="true">
  Per-series live dots: `radius`, `ring`, opt-in static `glow`, `color`,
  `pulse`, `valueLine`, and `valueLabel`. The crisp contrasting outer `ring`
  is on by default; `glow` is off by default and accepts `color`, `radius`,
  `blur`, and `opacity`. Pass `ring: false` for a flat circle, `dot={false}`
  to hide the dots, or `color` to override the per-series fill. (The deprecated
  `dot={{ show: false }}` still hides them.)
</ParamField>

## Scrub

<ParamField body="scrub" type="boolean | ScrubConfig" default="true">
  Crosshair scrubbing on drag. **As of v2 this defaults to `true`** (it previously
  defaulted to `false`); pass `scrub={false}` to disable. The existing default is
  a guide/dim layer. Omitting `seriesTooltip` (or setting it to `false`) preserves
  that behavior. Set `scrub.seriesTooltip` to opt into the Morfi-style
  time-range pill, one colour/value pill and intersection dot per visible series,
  collision stacking, and edge flipping. `seriesTooltip.alwaysShow` keeps value
  pills pinned to the visible endpoints while idle without showing the guide or
  time pill. The existing `scrub.tooltip={false}` switch remains the master
  tooltip control and also suppresses the per-series pills. See
  [Multi-series tooltips](/guides/multi-series#per-series-scrub-tooltip).
  `crosshairFadeDistance` and `crosshairLineCap` style the visible guide,
  selection dot, and tooltip consistently with `LiveChart`.
</ParamField>

<ParamField body="selectionDot" type="boolean | SelectionDotConfig" default="false">
  Dot drawn at the scrub intersection while scrubbing. **Hidden by default on
  `LiveChartSeries`** (unlike `LiveChart`): with multiple lines the dot can only
  track the leading series, so the crosshair and the opt-in tooltip's per-series
  intersection dots mark the scrub point instead. Pass `true` to opt in (it anchors to the leading series),
  a config to set `size` / `color` / `ring`, or `{ component }` for a fully
  custom Skia dot. See [Scrubbing](/guides/scrubbing#selection-dot).
</ParamField>

<ParamField body="onScrub" type="(point: ScrubPointMulti | null) => void">
  **Worklet** callback fired on the UI thread each frame while scrubbing; `null` when it ends.
  Includes a per-series value array. See [Scrubbing](/guides/scrubbing).
</ParamField>

<ParamField body="onGestureStart" type="() => void">
  JS-thread callback fired once when the user starts scrubbing. Respects
  `scrub.panGestureDelay` (it fires when the pan activates, not on first touch).
</ParamField>

<ParamField body="onGestureEnd" type="() => void">
  JS-thread callback fired once when the user stops scrubbing. Fires only if a
  scrub actually started — a tap that never activates emits neither callback.
</ParamField>

<ParamField body="timeScroll" type="boolean | TimeScrollConfig" default="false">
  Pan back through history (same as `LiveChart`). Drag (or fling) to scroll; the
  chart stops auto-following until you return to the live edge. Setting it back to
  `false` while scrolled back glides the window back to the live edge (eased, not
  an instant jump; never frozen at the old position). Per-series dots / value
  labels track each series' value at the visible right edge while scrolled. Pass
  a [`TimeScrollConfig`](/api-reference/types#config-objects) with `overscroll`
  to pan or pinch past the oldest data and live edge into blank space
  (TradingView-style; default `0` keeps the hard stops).
  **@experimental.** See [Time-scroll](/guides/time-scroll).
</ParamField>

<ParamField body="returnToLive" type="boolean | ReturnToLiveConfig" default="true">
  Controls the glide back to live when `timeScroll` is switched off while scrolled
  back (same as `LiveChart`). `true` (default) eases over `450` ms, `false` snaps
  instantly, `{ duration }` sets a custom length. Sibling of `timeScroll` so it
  survives `timeScroll={false}`. **@experimental.** See
  [Time-scroll → Turning it back off](/guides/time-scroll#turning-it-back-off).
</ParamField>

<ParamField body="zoom" type="boolean | ZoomConfig" default="false">
  Pinch-to-zoom the visible window (same as `LiveChart`), anchored at the focal
  point. Composes with `timeScroll`. **@experimental.** See
  [Time-scroll](/guides/time-scroll#pinch-to-zoom-zoom).
</ParamField>

Attach a `ref` typed as [`LiveChartHandle`](/api-reference/types#imperative-handle) and call
`ref.current?.resetZoom()` to return the shared window to `timeWindow` and the live edge. This is
the same imperative reset exposed by `LiveChart`. See
[Time-scroll → Reset zoom from a button](/guides/time-scroll#reset-zoom-from-a-button).

<ParamField body="onVisibleRangeChange" type="(range: VisibleRange) => void">
  Called as the visible window changes (\~1 Hz) with `{ startSec, endSec,
      following }`. **@experimental.**
</ParamField>

<ParamField body="onReachStart" type="() => void">
  Called once when the left edge nears the earliest retained data — the cue to
  page in older history. **@experimental.**
</ParamField>

## Degen

<ParamField body="degen" type="boolean | DegenOptions">
  Chart shake + spark burst off the leading series' dot on an upward swing.
</ParamField>

<ParamField body="onDegenShake" type="(payload: DegenShakePayload) => void">
  JS-thread callback when a degen shake starts.
</ParamField>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.