Projection Line

Forecast segment extending a line series past the last data point — dashed stroke, gradient, and horizon marker

Preview

Installation

pnpm dlx shadcn@latest add @bklit/projection-line

Usage

ProjectionLine draws a segment from the last data row (the anchor) into the future. It renders outside the series reveal clip so the horizon stays visible while the main line animates in.

Build the path with buildProjectionPath, or pass manual { date, value }[] points. Pair with LineSeriesTerminalMarker at the anchor when you want a ring at the hand-off.

import {
  buildProjectionPath,
  ChartTooltip,
  Grid,
  Line,
  LineChart,
  LineSeriesTerminalMarker,
  ProjectionLine,
  XAxis,
} from "@bklitui/ui/charts";

const projectionPath = buildProjectionPath({
  sourceData: chartData,
  seriesKey: "value",
  mode: "target",
  pathDensity: "endpoints",
  horizonPoints: 6,
  endValue: 301,
});

<LineChart data={chartData}>
  <Grid horizontal />
  <Line dataKey="value" strokeWidth={2} />
  <LineSeriesTerminalMarker dataKey="value" />
  <ProjectionLine
    data={projectionPath}
    strokeDasharray="1,4"
    curveKind="bezier"
    strokeStyle="gradient"
    gradientStart="oklch(0.979 0.037 110.273)"
    gradientEnd="oklch(0.59 0.17 166.38)"
    showEndMarker
  />
  <XAxis />
  <ChartTooltip />
</LineChart>

The chart extends its x-domain to fit the projection horizon. Projections are intended for line charts without brush zoom — the two features are not supported together.

ProjectionLine props

PropTypeDefaultDescription
dataProjectionPoint[]requiredAnchor + horizon points ({ date, value })
yAxisIdstring | number"left"Y-scale group id
strokestringvar(--chart-3)Solid stroke color
strokeStyle"solid" | "gradient""solid"Solid or path-aligned gradient stroke
gradientStartstringstrokeGradient start when strokeStyle is "gradient"
gradientEndstringvar(--chart-5)Gradient end when strokeStyle is "gradient"
strokeWidthnumber2Stroke width
curveKind"linear" | "bezier""linear"Straight segment or horizontal-tangent S-curve
strokeDasharraystring"6,4"Dash pattern
strokeOpacitynumber1Stroke opacity
showEndMarkerbooleantrueHorizon endpoint dot (ProjectionLineEndMarker)
endpointRadiusnumber5Horizon marker radius

buildProjectionPath

OptionTypeDefaultDescription
sourceDataRecord<string, unknown>[]requiredChart rows
seriesKeystringrequiredY value key
xDataKeystring"date"X value key
mode"auto" | "target" | "manual"requiredHow future points are generated
autoMethod"linearRegression" | "lastSegment""linearRegression"Slope for mode="auto"
pathDensity"stepped" | "endpoints""endpoints"Stepped path vs anchor + end only
horizonPointsnumber6Future intervals for auto/target modes
endValuenumberTarget Y when mode="target"
pointsProjectionPoint[]Manual path when mode="manual"
startIndexnumberlast rowAnchor row index

Terminal marker

LineSeriesTerminalMarker renders a hollow ring at the last data point for the given dataKey. It fades in after the clip reveal completes.

PropTypeDefaultDescription
dataKeystringrequiredSeries to anchor
yAxisIdstring | number"left"Y-scale group id
fillstringtransparentDot fill
strokestringvar(--chart-1)Ring color
radiusnumber5Dot radius
ringGapnumber0Gap between dot and ring
strokeWidthnumber1.5Ring stroke width

Studio

Edit in Studio

Open in Studio

Open Studio with a projection and use Settings → Projections or the series context menu to add a projection line. Tune stroke, dash, curve, and terminal marker in the layers panel.

Examples

Auto forecast with terminal marker

<LineChart data={chartData}><Grid horizontal /><Line dataKey="value" strokeWidth={2} /><LineSeriesTerminalMarker dataKey="value" /><ProjectionLine  data={projectionPath}  strokeDasharray="6,4"  curveKind="bezier"  showEndMarker/><XAxis /><ChartTooltip /></LineChart>

Gradient stroke

  <ProjectionLine  data={projectionPath}  strokeStyle="gradient"  gradientStart="oklch(0.926 0.128 16.866 / 0.73)"  gradientEnd="oklch(0.849 0.232 16.498)"  curveKind="bezier"  strokeDasharray="1,4"/>

See Projection on the line chart gallery.