LiveChart renders one series in line or candlestick mode. Props marked required must be
provided; everything else has a default.
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.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"). 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 contrasting outer halo, on by default), and color — ring: false
gives a flat dot, color overrides the fill. 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.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. 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):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, value band, or time band). 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. The
value is always a SharedValue, so the split tracks a
live benchmark (break-even / average cost, VWAP, previous close, a peg) on the
UI thread without re-rendering. Optionally adds a tinted profit/loss fill band
and a dashed marker line. Supersedes line.color/colors and segment
recoloring for the main stroke while set. See
ThresholdConfig. Single-series,
line mode only.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, or 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).
@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.(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. Use { labelRightMargin, gridEndGap } for a fixed right-anchored label column and deterministic gap
between labels and grid/plain reference lines.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”. The loading→live reveal
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); 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. 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.
number
Hard upper bound for the Y-axis range.
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 fewer than two samples and
loading is false.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.