Skip to content

v4.27.0 — Chart controls and reference tags

Choose a tag to compare

@brandtnewlabs brandtnewlabs released this 09 Oct 18:23
· 22 commits to main since this release
b560dfc

[4.27.0] — 2026-10-09

Added

  • referenceLineGrouping.mode: "stack" keeps individual reference tags readable
    using measured bounds and independent horizontal columns. Supports name/value
    pills, custom tags, off-axis pins, and moved press/drag targets without changing
    price strokes. Stack mode avoids the visible live value badge by default via
    avoidValueBadge; custom renderers receive tagOffsetY. Existing collapse
    behavior remains the default. The Working orders demo compares all three modes.
    (#377)

  • Opt-in yAxis.scaleGesture for line, candle, and multi-series charts, with
    exported YAxisScaleGestureConfig: drag the actual price gutter down to
    widen the range or up to zoom in, and double-tap to reset. Supports bounded
    scaling, configurable sensitivity, and either a supplied yRangeScale or
    internal state. Uses live layout/label measurements and leaves interactive
    overlays and plot gestures intact. The Y-range scale demo now uses it.
    (#376)

  • ReferenceLine.valueBadge and exported ReferenceLineValueBadgeConfig: a
    separate UI-thread price pill for horizontal reference lines, positioned in
    the plot or aligned with the right price column. Name/value pills share drag
    values, connector geometry, off-axis pinning, custom-renderer replacement,
    and grouping. The Working orders demo includes placement and axis controls.
    (#375)

  • Opt-in scrub.markers on LiveChart and LiveChartSeries, with exported
    ScrubMarkerConfig: return timestamp-matched markers and their data through
    onScrub, plus a UI-thread markers shared value in LiveChart.renderTooltip.
    Line charts use a configurable horizontal radius (default 16 px); candle
    charts select the hovered bucket. Matches include stacked/collapsed members
    in input order. The Markers & trades demo includes line/candle inspection.
    (#366)

  • xAxis.gridLines on LiveChart and LiveChartSeries: vertical grid lines at
    the time labels, drawn behind the series in the horizontal grid's layer and
    fading with their labels at the plot edges. true uses the gridStyle look;
    a GridStyleConfig overrides only the fields it sets. They run through a
    candle chart's volume band to the axis line, stay within the plot width, and
    follow LiveChart's axisAutoHide. Off by
    default. The Axes & grid demo has a toggle for them.

  • Experimental LiveChart.viewport (false | ViewportConfig) and exported
    ChartViewportControl / ViewportConfig: adopt
    app-owned shared values for scroll/zoom, with gestures writing the same pair.
    External overrides survive base-window and gesture-setting changes, honor
    future right edges, and wake autoSleep. Followers can set
    windowSmoothing: false to copy the leader's drawn width without easing twice.
    Omitted/false uses private state; behavior defaults resolve at render time in
    the shared config resolver, preserving the supplied shared values by reference.

  • A Synced charts demo and guide: one instrument in 1m/15m candle panes,
    leader selection, reset, base-window changes, and idle engine counters.

  • minRange on LiveChart and LiveChartSeries: the smallest Y span the
    auto-fit shows, in data units. Near-flat data widens to it around its
    midpoint instead of zooming in until every grid label reads the same, e.g.
    minRange={priceIncrement * 4}. On a nonNegative chart or under
    maxValue the span slides off the bound rather than shrinking, even when the
    ordinary fit's margin is clipped. If both hard bounds leave less room than
    the floor, they win; manual zoom applies afterward. Invalid or overflowing
    floors are ignored. Omitted, the fit is unchanged.

  • A Minimum Y range demo and matching guide with rounded-label comparisons,
    zero/ceiling bounds, line/candle/series modes, static updates, manual zoom,
    and a simulator walkthrough.

  • onScrubCandleChange on LiveChart (candle mode): called when the scrub
    crosshair enters or revisits a candle, with an OHLC snapshot on the JS thread.
    Sends null when the scrub ends, enters a gap, or leaves candle mode.
    Unlike onScrub, which fires every frame on a live chart, it fires once per
    candle, e.g. for a haptic tick per candle.

  • A discoverable Candle feedback demo with entry/exit counts, a gap, a ticking
    forming candle, haptics, and an optional per-frame callback comparison, with a
    matching guide and simulator recording.

  • A discoverable Badge alignment demo with centered/column comparison,
    repeatable $99.95 / $100.00 transitions, and controls for axis layouts,
    gutter width, badge font, tail, and offset, with a matching guide and recording.

  • BadgeConfig.textAlign ("center" | "yAxisColumn", default "center"):
    "yAxisColumn" lines the right-gutter live badge's value up with a
    right-anchored Y-axis label column (yAxis.labelRightMargin). The value
    starts at the labels' left X, a value wider than every axis label ends at the
    column's right edge, and it stays within the pill's padding. Centered, the
    value sits half the pill's spare room off the column even with matching badge
    metrics, and the automatic right inset leaves a digit spare (it sizes for the
    value ×10). The value moves with the column's width; the axes guide shows a
    matching metrics.badge and insets.right setup.

Changed

  • LiveChart reuses its gesture configurations and composition across reference
    level updates and replacement JS callbacks. Cached config/layout results avoid
    rebuilding unrelated interaction inputs. Reference drags read current line
    props on the UI thread; JS callbacks use the latest committed props. Gesture
    recognition and numeric layout changes still invalidate the relevant configuration;
    equivalent padding from recreated inline configs keeps scrub gestures cached.
    Completes the gesture follow-up to #383 (#373).
  • LiveChart is memoized, so a parent render with unchanged props no longer
    re-runs the chart. Pass stable references (memoized arrays and callbacks) to
    benefit; live data still flows through SharedValues as before.
  • Reference lines, gap bands and the renderReferenceLine /
    renderOffAxisReferenceLine probes are only re-resolved when
    referenceLines, candleGaps / lineGaps or those renderers change, not on
    every render. A chart without gaps also keeps a stable crosshair gap list.

Fixed

  • Static single-series charts now re-settle when yRangeScale or nonNegative
    changes without replacing data, so a manual zoom also updates a floored fit.
  • The right gutter for y-axis labels and the value badge now re-measures once
    the first real value arrives, instead of staying sized for a 0 placeholder
    and clipping labels like $87,000. LiveChart and LiveChartSeries skip
    0 and non-finite values when sampling, and re-measure only when the value
    moves a full order of magnitude. Multi-series charts sample the largest finite
    magnitude, so negative values alongside zero placeholders are measured too.
  • With yRangeScale below 1, the line, area fill, candles and gap bridges
    are now clipped to the plot's vertical extent instead of drawing past its top
    and bottom and over the time axis. In candle mode the clip stops at the price
    plot, above the volume band. Applies to LiveChart and LiveChartSeries.
  • xAxis.minGap now sets the minimum spacing between time labels on
    LiveChart and LiveChartSeries. It was resolved but never applied, so the
    labels always kept the default 60 px spacing. Changing the gap also replaces
    the label set immediately on paused or parked charts, so old labels cannot
    remain at the previous spacing while their fade waits for engine frames.
  • Static single-series charts now re-settle when nowOverride changes, and a
    chart that becomes static in the same render as new data (e.g. a recycled
    list cell) lands fully on the new window instead of stopping part way or
    keeping the previous right edge.
  • A dragged reference line stays under the finger when the price range changes
    or the plot is resized while the finger rests (live data, a rangeAnimation
    easing): it is re-mapped from the finger's position with the same snap and
    bounds, and its tag, grouping, press target and onDragIn / onDragOut
    follow it in the same frame. onCommit gets the value under the finger.
    onChange still reports finger moves (plus one catch-up on release if the
    line ended elsewhere), and the range still fits the value the finger last set,
    so a line held near the plot's edge doesn't push the range out every frame;
    dropped there, it widens the range once.
  • With snap, a line dragged to the plot's top or bottom edge is drawn and
    dropped on the nearest increment inside the visible range instead of just
    past it. Dragged past the edge, the value the finger sets rounds outward, so
    even a coarse snap can widen the range.
  • If lines added or removed mid-drag move a dragged line with an id to
    another index, the drag lets go: it stops following the finger and commits
    nothing, instead of moving and committing the line that took that index. That
    line immediately gets its own value back in place of the dragged value it
    inherited by index, even while the finger rests. Bringing the original line
    back before release does not resume the cancelled drag.
  • Removing the line being grabbed or dragged no longer throws on the UI thread
    (reading value as the drag starts or on release, or snap on the next
    move); the drag lets go.
  • Markers are no longer drawn up to 24 px past the plot's left and right edges.
    A marker now disappears as soon as its anchor leaves the plot, so panning
    back no longer slides it over the y-axis labels in a right- or left-side
    gutter, and onMarkerPress no longer fires for it there. A glyph anchored
    just inside an edge still overhangs it by up to half its width. On the left
    this is a visible change: with the default 12 px inset, a marker scrolling
    out used to slide off the canvas; it now disappears at the plot's left edge.
    A marker dated after the chart's current time appears once that time is
    reached, at the right edge. The 24 px allowance above and below the plot is
    unchanged. Live markers stay visible while the time window expands, including
    during pinch zoom, by keeping timestamp rounding below half a visible pixel.
  • DotConfig, DotRingConfig, LineStyleConfig, ThresholdFillConfig, and
    TimeScrollConfig are now exported from the package root, which the Types
    reference says holds every type. Importing them from react-native-livechart
    no longer fails to typecheck.
  • The extrema labels guide's LineStyleConfig link points at the Config objects
    section of the Types reference instead of a missing anchor.