Skip to main content
Live example: app/demo/extrema-labels.tsx in the example app.

High / low labels pinned to the data points where they occur

topLabel / bottomLabel normally pin the high / low readout to the plot edge. A position variant moves them onto the data instead. position: "extrema" floats the label at the actual data point where the value occurs instead of pinning it to an edge — topLabel tracks the highest point, bottomLabel the lowest. The chart projects the extremum’s (time, value) to a canvas pixel each frame and positions a small dot + the value there on the UI thread, so it tracks the point as the chart scrolls and the Y-axis rescales. It’s the easiest way to show when the high / low happened, not just what it was.
The label hides itself when the window holds no data, or when the extremum scrolls off the plot (the engine re-picks the visible high / low every frame). It works in candle mode too — the extrema track the highest high / lowest low. "extrema-edge" is a variant that keeps the readout on a clean rail: the value label pins to the top / bottom edge (still horizontally aligned with the extremum), and a dot marks the actual point, joined by a connector line. Good when a point-anchored label would crowd the live dot or sit awkwardly mid-candle.
The connector defaults on (dashed) in "extrema-edge" mode; pass connector: false to drop it (value at the edge + dot on the point, no line), or a LineStyleConfig to style it. dot: false removes the dot. Style the built-in label without dropping to a custom render — fontSize, fontWeight, fontFamily size the value text, and dotColor, dotSize, and dot: false control the marker:
(fontSize / fontWeight / fontFamily style the edge "left" / "right" labels too; the dot* knobs are "extrema"-only.) For anything beyond that, a custom render is centered over the point instead of the built-in dot + value — you own the chrome:
The same props work on LiveChartSeries, where the bounds track the combined range of the visible series (and "extrema" marks the global high / low across them). The labels are display-only (pointerEvents="none"), so they never block scrubbing.