LiveChart renders one series in line or candlestick mode. Props marked required must be
provided; everything else has a default.
Series opacity
SharedValue<number>
default:"1"
A UI-thread opacity multiplier for the plotted data. Set it to
0.5 while
replacement history loads, then restore it to 1 when the new data arrives.
It affects the line and area fill, candles and volume bars, value line, badge,
and inline value text—not axes, reference lines, or scrub UI. While it is below
1, the live dot and pulse ring fade completely out so the stroke cannot show
through the dot; they fade back in after the multiplier returns to 1.
See Dimming replacement data.Data
SharedValue<LiveChartPoint[]>
required
Growing array of
{ time, value } points. Read on the UI thread.SharedValue<number>
required
Latest live value, interpolated between data updates.
Display mode
"line" | "candle"
default:"\"line\""
Line/area or OHLC candlestick rendering.
SharedValue<CandlePoint[]>
Committed OHLC bars, sorted by
time (candle mode).number
Seconds per candle bucket (e.g.
60 for 1-minute bars).SharedValue<CandlePoint | null>
In-progress candle, updated each tick;
null between buckets.CandleGap[] | CandleGapsConfig
default:"off"
Explicit no-trade, unavailable, or unknown candle intervals. The library never
infers their meaning from sparse timestamps and never inserts synthetic OHLC.
See Chart gaps.
ChartGap[] | ChartGapsConfig
default:"off"
Explicit no-trade, unavailable, or unknown line intervals. The line and every
area fill stop at empty interval boundaries; bridge-enabled kinds draw an
independently styled previous-value segment. Real samples take precedence.
See Chart gaps.
boolean | VolumeConfig
default:"false"
Volume bars in a reserved band below the candles (candle mode only). The
candle plot shrinks by the band height so candles are never cut off; the x-axis
stays pinned to the bottom. Reads each
CandlePoint.volume;
bars normalize to the largest visible volume. Pass a
VolumeConfig for upColor / downColor,
maxHeight, radius, opacity. See Candlestick.Line, fill & tip
LineConfig
Main line styling:
width, color, plus shape controls — curve
("monotone" smooth default | "linear" straight segments), join
("round" | "miter" | "bevel"), and cap ("round" | "butt" |
"square"). simplify is an opt-in screen-space path tolerance in pixels;
start around 0.75–1.5 to remove sub-pixel noise without changing the
source data, fitted range, markers, or scrub values. See
Line denoising. Pair curve: "linear" with
join: "miter" + cap: "butt" for a fully hard-edged (“edgy”) line.boolean | GradientConfig
default:"true"
Area fill under the line. Pass a
GradientConfig with colors (≥ 2 stops, top
→ bottom) for a custom multi-color fill; otherwise the fill is derived from the
accent color.boolean | AreaDotsConfig
default:"false"
Dot-lattice fill of the area beneath the line — a screen-fixed grid of dots
clipped to the region between the line and the baseline. Composes with
gradient (both paint) or replaces it (gradient={false}). Pass an
AreaDotsConfig to tune spacing, size, color, and opacity; the color
defaults to a faint tint of the line/accent color. Inert in candle mode.boolean | BadgeConfig
default:"true"
Value badge pill at the tip. Pass a
BadgeConfig to
shape it — radius (escape the capsule), borderColor / borderWidth,
textColor, per-badge fontSize / fontFamily / fontWeight, and
offsetX / offsetY. All are Skia-native and drawn in the batched canvas
pass, so there’s no per-frame view cost. See Theming → Customizing the
badge.boolean | PulseConfig
default:"true"
Pulsing ring on the live dot.
boolean | DotConfig
default:"true"
Live dot styling. Pass
false to hide the dot, or a DotConfig for radius,
ring (the crisp contrasting backing, on by default), opt-in glow, and
color. glow: true enables restrained defaults, or pass a DotGlowConfig
to tune color, radius, blur, and opacity. It is independent from
the animated pulse prop and starts no animation clock. The same DotConfig
is shared with LiveChartSeries (whose dot extends it with pulse,
valueLine, and valueLabel). dot={false} is the canonical “hide” — the
deprecated dot={{ show: false }} still works. With timeScroll,
trackWhileParked keeps the dot on the true live point while scrolled
back — it tracks the point’s x, keeps its pulse, and hides once the point
leaves the window (ignored with badge.followViewEdge). See
Time-scroll.boolean | ValueLineConfig
Horizontal dashed line at the current value.
boolean
default:"false"
Render the live value as large top-left text.
boolean
default:"false"
Tint the
showValue text by momentum (green up / red down).Momentum & degen
boolean | "up" | "down" | "flat" | MomentumConfig
default:"true"
Momentum-based dot/badge coloring. See Momentum & degen.
boolean | DegenOptions
Particle burst + screen shake on momentum swings.
(payload: DegenShakePayload) => void
JS-thread callback when a degen shake starts.
Trades, markers & references
SharedValue<TradeEvent[]>
Live trade fills for on-chart markers.
SharedValue<Marker[]>
Glyph markers drawn into the canvas (UI-thread read).
(event: MarkerPressEvent | null) => void
Fires when a marker is tapped;
null on a miss. When a collapsed cluster (count
badge) is tapped, event.isGrouped is true and event.members lists the
cluster’s markers.number
default:"16"
Tap hit-test radius in px.
"anchored" | "stacked" | MarkerClusterConfig
default:"\"anchored\""
Collision handling for co-located markers. For Custom collapsed look — by default a collapsed group draws a round count
badge (
"anchored" (default) keeps today’s
behavior — glyphs draw at their anchor and overlap. "stacked" fans co-located
markers apart horizontally (overlapping, left-over-right) along their
side, collapsing a cluster into a single
count-badge marker once it exceeds maxBeforeGroup. Grouping is recomputed per
frame, so a cluster fans back out as you zoom/scroll in. Pass a
MarkerClusterConfig object to tune the
overlap (0–1, default 0.75) and maxBeforeGroup (default 5):direction: "vertical", maxVisible caps the column while preserving the
oldest glyphs nearest the line; newer overflow is hidden. It defaults to
unbounded. maxBeforeGroup still runs first, so set it higher than the burst
you want to cap instead of collapse:groupBadge: "count"). Two ways to customize it:groupBadge: "marker"— draw the representative marker’s own glyph (itsimage/icon/pill/kind), e.g. a run of buy pills → a buy pill.groupBadge: { image }(or{ icon, pill, color }) — a dedicated badge you supply (MarkerGroupBadge), independent of the members — e.g. tiny dots that collapse into a distinct “Buy 5” image.
showGroupCount to stamp the member count in the glyph’s corner. All are
Skia-drawn in the same batch as every other marker (not a renderMarker RN
overlay).(marker: Marker, ctx: MarkerRenderContext) => ReactElement | null
Render a marker as a custom React Native element instead of a built-in Skia
glyph — e.g. an
expo-blur glass badge or any non-Skia view. Return an element
to float it, auto-centered, at the marker’s live (time, value) position
(tracked on the UI thread); return null/undefined to keep the built-in
glyph. The second argument carries cluster/position state
({ index, isGrouped, groupCount, side }) — e.g. render a distinct collapsed
look when ctx.isGrouped. Custom-rendered markers skip the atlas (no
double-draw) and stay crisp at native resolution. Use sparingly — each is its
own animated view, whereas built-in glyphs batch into one draw call. See
Custom marker rendering.(ctx: TooltipRenderProps) => ReactElement | null
Render a fully custom scrub tooltip as a React Native element instead of the
built-in pill — the same idea as
renderMarker. The chart floats it over the
canvas and positions it on the UI thread (per scrub.tooltipPlacement); you own
the chrome (border radius/color, background are plain RN styles) and content. Bind
the TooltipRenderProps SharedValues
to animated text so the value/date update on the UI thread too — smooth, unlike
rebuilding the tooltip from the JS-thread onScrub. Return null/undefined to
fall back to the built-in pill. Line mode only (candle keeps its OHLC stack).
See Custom tooltip.(ctx: ChartOverlayContext) => ReactElement | null
Render a custom overlay floated over the canvas, handed the price↔pixel /
time↔pixel bridge so it can track the auto-rescaling axis on the UI thread —
the same idea as
renderMarker. The
ChartOverlayContext gives you a
per-frame scale SharedValue plus pure priceToY / yToPrice / timeToX /
xToTime mapping worklets. Easiest: render a component per level and call
usePriceY(ctx, price) /
useTimeX(ctx, time) — each returns a SharedValue<number> that tracks the axis,
which you read in useAnimatedStyle. (Or take the manual path: read scale.get()
in the worklet, then feed the snapshot to the mappings.) Return any RN view tree
(order / avg-entry / liquidation price tags, custom level lines); return
null/undefined for no overlay. The tree mounts full-bleed with
pointerEvents="box-none" so empty areas still scrub. Available on both
LiveChart and LiveChartSeries. See Overlay bridge.ReferenceLine[]
Reference lines / bands (horizontal line, time-varying
series, value band, or
time band). Series lines work in both line and candle mode and extend their last
value to the live edge unless extendToNow is false. Form-A lines can be
draggable (drag to set a price, with snap / bounds and onChange /
onCommit / onDragIn / onDragOut callbacks). See
Reference lines.(ctx: ReferenceLineRenderProps) => ReactElement | null
Render a reference line’s tag as a custom React Native element instead of the
built-in Skia pill / gutter label — the same model as
renderMarker /
renderTooltip. The chart floats it over the canvas and pins it to the line’s
value on the UI thread (see
ReferenceLineRenderProps), so it tracks the
rescaling axis and any drag without JS re-renders. Called per Form-A line; return
null to keep that line’s built-in tag (works with badge: false too).
A left- or right-pinned badge keeps its built-in dashed connector, which starts
after the measured custom view. Single-series only.(ctx: ReferenceLineRenderProps) => ReactElement | null
Replace only a Form-A line’s off-axis tag with a React Native element. The
standard Skia tag or gutter label remains visible in range; the custom view takes
over only when the value is pinned above or below the plot. A left- or
right-pinned
badge (or legacy offAxisBadge) keeps its native dashed connector,
beginning after the measured custom view. Return null for lines that opt out;
use ctx.edge inside the returned component to animate a directional caret. See
Reference lines.boolean | ReferenceLineGroupingConfig
default:"false"
Collapse Form-A lines whose handles sit near the same value into a single count
handle — a stack of working orders at adjacent prices reads as one tag. Pass an
object to tune the proximity
radius (px). Single-series only.ChartSegment[]
Labeled time-range segments (sessions, after-hours, overnight) with
scrub-focus: at rest the line is one uniform color; while scrubbing — or
when a segment is
active — the focused segment keeps the base color and every
other segment is de-emphasized (mutedColor / mutedColors) by recoloring the
line stroke itself, not an overlay. Optional dashed divider + label mark a
segment’s edge. See Segments and
ChartSegment. Single-series only.ThresholdConfig
Color the line above vs. below a live threshold value — green above, red below
by default. Use a live scalar
SharedValue<number>, a LiveChartPoint[]
history, or a live SharedValue<LiveChartPoint[]> series.
Optionally adds a tinted profit/loss fill band and a dashed marker line; a
series marker badge can independently select its
horizontal labelPosition and first/last visible labelAnchor. Supersedes
line.color/colors and segment recoloring for the main stroke while set. See
ThresholdConfig. Single-series,
line mode only.(ctx: ThresholdBadgeRenderProps) => ReactElement | null
Replace the built-in Skia threshold pill with a custom React Native
element. The chart measures it and pins it to the threshold’s live Y position
and
threshold.line.labelPosition on the UI thread; the dashed marker line
remains native. The context exposes value, valueStr, y, and visible
SharedValues plus the resolved line config. Return null/undefined to keep
the built-in badge. Requires threshold.line. See
Custom threshold badge.Scrubbing
boolean | ScrubConfig
default:"true"
Crosshair scrubbing on drag.
crosshairFadeDistance controls the visible
line/dot/tooltip fade near the live edge, and crosshairLineCap selects a
"butt", "round", or "square" vertical-line cap. See
Scrubbing.boolean | SelectionDotConfig
default:"true"
Dot drawn at the scrub intersection while scrubbing.
false hides it; pass a
config to set size / color / ring, or { component } for a fully custom
Skia dot. See Scrubbing.(point: ScrubPoint | null) => void
Fires while scrubbing;
null when it ends.boolean | ScrubActionConfig
default:"false"
Order-ticket mode: tap to drop a locked crosshair, drag to fine-tune a
price level, then press the right-gutter action badge to fire
onScrubAction.
The reported price is the value at the reticle’s Y (a free level you choose),
not the line value at that time. Coexists with scrub. Pass a
ScrubActionConfig for icon, colors,
snap, text: false (icon-only), or timeBadge (an x-axis date/time pill, off by
default). See Order ticket.
Single-series only.(point: ScrubActionPoint) => void
JS-thread callback fired when the action badge is pressed.
point.price is the
chosen price level (reticle Y, optionally snap-rounded). See
ScrubActionPoint.() => void
JS-thread callback fired once when the user starts scrubbing. Respects
scrub.panGestureDelay (it fires when the pan activates, not on first touch).() => 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.
boolean | TimeScrollConfig
default:"false"
Pan back through history: drag (or fling) to scroll, and the chart stops
auto-following until you return to the live edge. Setting it back to
false
while scrolled back — or switching mode so it’s no longer passed — glides the
window back to the live edge (eased, not an instant jump; never frozen at the
old position).
true uses the default drag-to-scroll gesture ("holdToScrub" — drag scrolls,
press-and-hold scrubs); pass a
TimeScrollConfig to pick "axisDrag"
(drag the x-axis strip), set scrubHoldMs, set
hideLiveOnScrollBack: false to keep the live badge, dot, and value line visible
while scrolled back (hidden by default — they mark the off-screen live price), or
set overscroll to drag past the data bounds into blank space
(TradingView-style; default 0 — hard stops).
@experimental. See Time-scroll.boolean | ReturnToLiveConfig
default:"true"
Controls the glide back to the live edge when
timeScroll is switched off while
scrolled back. true (default) eases onto live over 450 ms; false snaps
instantly; { duration } sets a custom glide length (ms). Kept separate from
timeScroll so it survives timeScroll={false} (the toggle that triggers it).
@experimental. See
Time-scroll → Turning it back off.boolean | ZoomConfig
default:"false"
Pinch-to-zoom the visible time window. Two-finger pinch in/out narrows or
widens the window, anchored at the focal point between your fingers. Composes
with
timeScroll (zoom level and scroll position are independent). true uses
sensible default bounds; pass a ZoomConfig
to set minTimeWindow / maxTimeWindow. @experimental. See
Time-scroll.Resetting pinch zoom
Attach aref typed as LiveChartHandle and call
ref.current?.resetZoom() from a button or any other outside event. It returns the visible width
to timeWindow, clears the focal-point offset, and resumes following the live edge. The reset is
scheduled on the UI thread and is safe when the chart is already reset. A paused chart remains
paused. See Time-scroll → Reset zoom from a button.
(range: VisibleRange) => void
Called as the visible window changes (throttled to ~1 Hz) with
{ startSec, endSec, following }. Useful for paging a data source alongside
timeScroll / zoom. @experimental.() => void
Called once when the window’s left edge comes within one window-width of the
earliest retained data — the cue to lazily load older history. Re-arms after
the edge moves back out. @experimental.
Axes, grid & range
boolean | XAxisConfig
default:"true"
Time-axis labels.
boolean | YAxisConfig
default:"true"
Value-axis grid + labels. Pass
{ count } for a fixed number of evenly-spaced
prices instead of the dynamic nice-interval grid. Pass { intervalScale }
with a matching formatValue multiplier to choose nice intervals in display
units without changing plotted values. Scales that would make the current
display range overflow or underflow fall back to source-unit intervals. Use
{ labelRightMargin, gridEndGap } for a fixed right-anchored label column and
deterministic gap between labels and grid/plain reference lines.boolean | AxisAutoHideConfig
default:"false"
Fade the X and Y axes (grid, ticks, and labels) out while the chart is idle,
then show them for scrubbing, panning, fling momentum, and pinch zoom.
true
uses the default timing; pass
AxisAutoHideConfig to set the fade
durations, idle opacity, and idle delay. Experimental; LiveChart only.
See Axis auto-hide.boolean | AxisLabelConfig
default:"false"
Edge label floated at the plot’s top.
true shows the built-in value
label — the chart’s current top Y-axis bound, formatted and updated each frame
(Robinhood-style high). Pass AxisLabelConfig
to set format / color / position, or { render } to float a fully custom
element instead. See Axis labels.boolean | AxisLabelConfig
default:"false"
Edge label floated at the plot’s bottom.
true shows the built-in value
label — the chart’s current bottom Y-axis bound (the low) — with the same
AxisLabelConfig knobs and render escape hatch as topLabel.GridStyleConfig
Grid-line color / width / dash / opacity.
number
default:"30"
Visible window in seconds.
boolean
default:"false"
Freeze scrolling; resume catches up to real time.
boolean | LoadingConfig
Breathing-line loading shell until data is ready.
true uses the defaults; pass
a LoadingConfig to restyle it (color,
strokeWidth, amplitude, speed, and axisLabels to toggle the skeleton
Y-axis placeholders). false / omitted is “not loading”. Entering loading or
empty snaps immediately; the loading→live grow-in duration is set via the
transitions prop below — see
Transitions.boolean | TransitionConfig
Tune or disable the built-in transition animations.
true / omitted keeps the
defaults; false makes them instant (no grow-in when data appears or the
timeframe changes, no candle↔line crossfade, candle width snaps); leaving
live data for loading/empty already snaps; a
TransitionConfig sets per-transition
durations in ms — reveal (default 600) and mode (default 300), 0 to
snap — plus candleLerpSpeed (default 0.08, 1 = instant), the per-frame
speed at which candle bodies resize when candleWidth changes (a timeframe /
bucket switch). Live value tracking is governed separately by smoothing, and
static-entry suppression by static. See Transitions.boolean
default:"false"
Render once with no per-frame animation loops — engine, degen, trades, candles,
markers, pulse, and entry reveal are all disabled.
scrub / scrubAction stay
available, though: they’re on-demand touch gestures with no per-frame cost, so a
still chart costs nothing at rest yet is still scrubbable on touch. Keeps many
small charts cheap when you render a list or grid of sparklines. You can toggle
it at runtime; switching back to live restarts the suspended loops and catches
up. Frame the data edge-to-edge with timeWindow + nowOverride. See the
Sparklines guide.number
default:"0.08"
Value-lerp speed (0 = frozen, 1 = instant).
string | number
Snap the framing (time window, Y-range, value) to its target in one frame
whenever this key changes — without giving up smooth live ticks. On a
timeframe / dataset switch the framing otherwise eases over
smoothing, which
reads as a slide; bump snapKey (e.g. to the current timeframe id, or a counter
you increment when swapping data / candles) and the next frame jumps to the
new framing, then normal smoothing resumes. Unlike transitions (opacity only)
and static (no live loop), this settles only the geometry and only for one
frame. See Transitions.boolean
default:"false"
Tight Y-axis so small moves fill the height.
boolean
default:"false"
Clamp the Y-axis lower bound at 0. When
yRangeScale
zooms out, expansion stops when that floor is reached, keeping the data
centered rather than growing only upward.number
Hard upper bound for the Y-axis range.
SharedValue<number>
default:"1"
Manual Y-range multiplier around the fitted midpoint (
1 = auto-fit). Drive
it from a gesture (e.g. dragging the price axis) to stretch or compress the
price scale TradingView-style; the auto-fit keeps tracking the visible window
underneath. Values must be positive and finite; invalid values safely fall
back to 1. On a nonNegative chart, zoom-out stops at the zero floor.
Read on the UI thread each frame. Shared with LiveChartSeries.
@experimental. See
Manual Y-range scaling.number
default:"0"
Right-edge buffer as a fraction of
timeWindow.number
Override the engine’s “now” (unix seconds) — useful for historical playback.
Theming & layout
"transparent" | "opaque"
default:"\"transparent\""
Experimental canvas composition mode. On Android,
"transparent" uses Skia’s default
TextureView path; "opaque" owns and paints the palette background and selects SurfaceView.
Keep the default when content behind the chart must remain visible. Profile release builds on
physical hardware before enabling broadly. See Android surface rendering."light" | "dark"
default:"\"dark\""
Color scheme.
string
default:"\"#3323E6\""
Primary accent; the palette is derived from it.
Partial<LiveChartPalette>
Override individual resolved-palette keys.
LiveChartMetricsOverride
Sizing & motion tokens — the geometry/feel analogue of
palette. Namespaced
(badge, candle, grid, motion, emptyState); only the keys you set are
replaced. See the Theming guide and
LiveChartMetrics.FontConfig
Font family / size / weight / custom typeface for all chart text.
boolean | LeftEdgeFadeConfig
default:"true"
Soft fade on the left edge.
ChartInsets
Padding for the drawing area (
top, right, bottom, left).ViewStyle
Container
View style.Text & accessibility
(v: number) => string
Formatter for value labels (axes, badge, tooltips).
(t: number) => string
Formatter for time labels.
string
default:"\"No data\""
Label shown when there are no samples and
loading is false. A single line point or
committed candle is valid data and renders normally.string
Accessibility label for the chart container.
"image" | "none" | "adjustable" | "summary"
default:"\"image\""
Accessibility role for the container.
Config-object types (
LineConfig, BadgeConfig, DegenOptions, ReferenceLine, etc.) are
documented in the Types reference.