Profit/Loss Line

Sign-colored line segments for profit and loss on a shared zero baseline

Profit
Loss

Installation

pnpm dlx shadcn@latest add @bklit/profit-loss-line

Usage

Use ProfitLossLine inside LineChart for a single series that crosses zero. Pair it with a hidden Line (same dataKey) so the chart registers the series for the y-domain and tooltip. Highlight the zero baseline with Grid highlightRowValues.

import {
  LineChart,
  Line,
  Grid,
  XAxis,
  ChartTooltip,
  ProfitLossLine,
  profitLossColor,
  resolveProfitLossTooltipLabel,
} from "@bklitui/ui/charts";
import { curveLinear } from "@visx/curve";

const data = [
  { date: new Date("2024-01-01"), pnl: 420 },
  { date: new Date("2024-01-02"), pnl: -180 },
  // ...
];

export default function ProfitLossChart() {
  return (
    <LineChart data={data}>
      <Grid highlightRowValues={[0]} horizontal />
      <Line
        curve={curveLinear}
        dataKey="pnl"
        fadeEdges={false}
        showHighlight={false}
        stroke="transparent"
        strokeWidth={0}
      />
      <ProfitLossLine dataKey="pnl" />
      <XAxis />
      <ChartTooltip
        indicatorColor={(point) => profitLossColor((point.pnl as number) ?? 0)}
        rows={(point) => {
          const value = (point.pnl as number) ?? 0;
          return [
            {
              color: profitLossColor(value),
              label: resolveProfitLossTooltipLabel(""),
              value,
            },
          ];
        }}
      />
    </LineChart>
  );
}

Components

ProfitLossLine

Renders linear segments colored by sign. Values ≥ 0 use emerald; values < 0 use red (Tailwind CSS variables by default).

PropTypeDefaultDescription
dataKeystringrequiredKey in data for y values
xDataKeystring"date"Key in data for x values
strokeWidthnumber2.5Line width
curveCurveFactorycurveLinearInterpolation curve (same as Line)
fadeEdgesFadeEdgesfalseFade stroke toward transparent at chart edges
positiveColorstringvar(--color-emerald-500)Color for profit segments
negativeColorstringvar(--color-red-500)Color for loss segments

ProfitLossLegend

Optional legend with Profit/Loss items. Hover dims the opposite segment when wrapped with ProfitLossLegendHoverProvider.

PropTypeDefaultDescription
hoveredIndexnumber | nullnullControlled hover index
onHoverChange(index: number | null) => voidHover callback
align"start" | "center" | "end""start"Horizontal alignment
classNamestringAdditional CSS class

Grid zero line

Use highlightRowValues={[0]} on Grid to emphasize the break-even baseline:

<Grid
  highlightRowValues={[0]}
  highlightRowStroke="var(--foreground)"
  highlightRowStrokeOpacity={0.35}
  horizontal
/>

See the Line Chart docs for full Grid props.

Interactive examples live on the line chart gallery under Profit/Loss.