Tooltip

An interactive tooltip component for charts with crosshair, dots, date picker, and customizable content

Preview

Installation

pnpm dlx shadcn@latest add @bklit/chart-tooltip

Usage

The ChartTooltip component provides hover interactions for charts. It must be used inside a chart component (LineChart, AreaChart, BarChart).

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

<LineChart data={data}>
  <Grid horizontal />
  <Line dataKey="value" />
  <ChartTooltip />
</LineChart>

Props

PropTypeDefaultDescription
showDatePillbooleantrueShow animated date ticker at bottom
showCrosshairbooleantrue (false in BarChart and jittered ScatterChart)Show the crosshair indicator line. Bar charts (vertical and horizontal) and ScatterChart with jitter (hover snaps to the nearest point, not a date) hide it by default — pass showCrosshair to opt in
showDotsbooleantrueShow dots on data points
indicatorColorstring | (point) => string—Crosshair and dot color; pass a function for dynamic colors
indicatorDasharraystring—SVG dash pattern for the crosshair (e.g. "4,4"). Omit for solid
indicatorFadeEdges"both" | "top" | "bottom" | "none""both"Vertical crosshair fade; none = solid line
indicatorFadeLengthnumber10Fade zone size (% of crosshair height) when fading
matchCrosshairbooleanfalseWhen true, the panel uses the crosshair spring and moves in sync
dampingnumber20Panel follow damping (default). 0 = instant. Ignored when matchCrosshair is true
springConfig{ stiffness: number; damping: number }chart configFull spring override for crosshair, dots, and date pill
boxSpringConfig{ stiffness: number; damping: number }chart configFull spring override for the floating tooltip panel
exitbooleantrueFade the panel out when hover ends. false hides it immediately
backgroundColorstringvar(--chart-tooltip-background)Panel background (CSS variable or color value)
panelStyleCSSProperties—Inline styles for tooltip background and blur
dotVariant"dot" | "ring""dot"Dot style on series markers. dot is a solid core with a soft same-color halo
dotSizenumber5Dot core / ring radius in pixels
dotHaloScalenumber2.6Halo radius as a multiple of dotSize; 0 hides the halo. Dot variant only
dotHaloOpacitynumber0.3Halo opacity (0–1). Dot variant only
dotRadiusFractionnumber—Ring corner radius as a fraction of side length (0 = square, 0.5 = circle). Ring variant only
dotScalenumber1Multiplier applied to the dot / ring radius
dotStrokeWidthnumber1.5 (ring) / 0 (dot)Ring stroke width; for the dot variant, a background-colored outline around the core
dotColorstring | (point, line) => string—Override dot/ring color (e.g. when fill is gradient/pattern)
content(props) => ReactNode-Custom content renderer
rows(point) => TooltipRow[]-Custom row generator
childrenReactNode-Additional content (e.g., markers)
classNamestring""Additional CSS class

TooltipRow Interface

interface TooltipRow {
  color: string;    // Dot color
  label: string;    // Row label
  value: string | number;  // Display value
}

Anatomy

The tooltip has several visual components:

  1. Crosshair - Vertical line that follows the cursor
  2. Dots - A solid dot with a soft halo in the series color on each data point at the hovered position
  3. Tooltip Box - Popover-style panel: a header row with the date / category, a full-width separator, then rows (color dot, muted label, right-aligned value)
  4. Date Pill - Animated date ticker at the bottom

Each component can be shown/hidden independently.

Examples

Default Tooltip

Full-featured tooltip with crosshair, dots, and date pill.

<LineChart data={data}>  <Grid horizontal />  <Line dataKey="users" stroke="var(--chart-line-primary)" />  <Line dataKey="pageviews" stroke="var(--chart-line-secondary)" />  <XAxis />  <ChartTooltip /></LineChart>

Solid crosshair

Remove vertical fade with indicatorFadeEdges="none" for a flat crosshair line.

<LineChart data={data}><Grid horizontal /><Line dataKey="users" stroke="var(--chart-line-primary)" /><XAxis /><ChartTooltip  showDots={false}  showDatePill={false}  indicatorFadeEdges="none"  indicatorColor="var(--chart-2)"/></LineChart>

Crosshair fade

Fade the crosshair from the top, bottom, both ends, or not at all. Use indicatorFadeLength to control how far the fade extends (percentage of chart height).

<LineChart data={data}><Grid horizontal /><Line dataKey="users" stroke="var(--chart-line-primary)" /><XAxis /><ChartTooltip  showDots={false}  showDatePill={false}  indicatorFadeEdges="top"  indicatorFadeLength={22}  indicatorColor="var(--chart-2)"/></LineChart>

Dashed crosshair

Pass an SVG dash pattern to indicatorDasharray.

<LineChart data={data}><Grid horizontal /><Line dataKey="users" stroke="var(--chart-line-primary)" /><XAxis /><ChartTooltip  showDots={false}  showDatePill={false}  indicatorDasharray="6,4"  indicatorColor="var(--chart-2)"/></LineChart>

Match crosshair

By default the tooltip panel eases independently with damping={20}. Set matchCrosshair to lock the panel to the crosshair spring.

<LineChart data={data}>  <Grid horizontal />  <Line dataKey="users" stroke="var(--chart-line-primary)" />  <XAxis />  <ChartTooltip matchCrosshair /></LineChart>

Panel damping

The default panel uses damping={20} without any props. Increase damping for heavier lag, or set damping={0} for instant follow.

<LineChart data={data}><Grid horizontal /><Line dataKey="users" stroke="var(--chart-line-primary)" /><XAxis /><ChartTooltip  damping={55}  indicatorColor="var(--chart-2)"/></LineChart>

Crosshair Only

Minimal tooltip with just the crosshair line and tooltip box.

<LineChart data={data}>  <Grid horizontal />  <Line dataKey="users" stroke="var(--chart-line-primary)" />  <XAxis />  <ChartTooltip showDots={false} showDatePill={false} /></LineChart>

Minimal (Box Only)

Just the tooltip content box, no visual indicators.

<LineChart data={data}><Grid horizontal /><Line dataKey="users" stroke="var(--chart-line-primary)" /><XAxis /><ChartTooltip  showCrosshair={false}  showDots={false}  showDatePill={false}/></LineChart>

Custom Row Labels

Use the rows prop to customize row labels and value formatting.

<LineChart data={data}><Grid horizontal /><Line dataKey="users" stroke="var(--chart-line-primary)" /><Line dataKey="pageviews" stroke="var(--chart-line-secondary)" /><XAxis /><ChartTooltip  rows={(point) => [    {      color: "var(--chart-line-primary)",      label: "Active Users",      value: point.users.toLocaleString(),    },    {      color: "var(--chart-line-secondary)",      label: "Page Views",      value: point.pageviews.toLocaleString(),    },  ]}/></LineChart>

With Bar Chart

The tooltip adapts to bar charts, showing category names instead of dates. Inside BarChart the crosshair line is hidden by default (only the hover dots and panel show); pass showCrosshair to bring it back.

<BarChart data={data} xDataKey="month"><Grid horizontal /><Bar dataKey="revenue" fill="var(--chart-line-primary)" /><BarXAxis /><ChartTooltip  rows={(point) => [    {      color: "var(--chart-line-primary)",      label: "Revenue",      value: `$${point.revenue.toLocaleString()}`,    },  ]}/></BarChart>

Fully Custom Content

Use the content prop for complete control over the tooltip layout.

<LineChart data={data}><Grid horizontal /><Line dataKey="users" stroke="var(--chart-line-primary)" /><Line dataKey="pageviews" stroke="var(--chart-line-secondary)" /><XAxis /><ChartTooltip  content={({ point }) => (    <div className="flex flex-col gap-2 p-3">      <div className="text-sm font-medium">        {point.date.toLocaleDateString("en-US", {          weekday: "short",          month: "short",          day: "numeric",        })}      </div>      <div className="grid grid-cols-2 gap-x-4 gap-y-1 text-sm">        <span className="text-zinc-400">Users</span>        <span className="font-mono">{point.users.toLocaleString()}</span>        <span className="text-zinc-400">Views</span>        <span className="font-mono">{point.pageviews.toLocaleString()}</span>        <span className="text-zinc-400">Ratio</span>        <span className="font-mono">          {(point.pageviews / point.users).toFixed(2)}x        </span>      </div>    </div>  )}/></LineChart>

Animation

The tooltip features smooth animations:

  • Tooltip panel - By default the panel eases with damping={20}. Set matchCrosshair to share the crosshair spring, or tune lag with damping (0–100) or boxSpringConfig.
  • Crosshair - Spring physics for snappy following (springConfig)
  • Crosshair style - Solid by default; pass indicatorDasharray="4,4" (or any SVG dash pattern) for a dashed line.
  • Tooltip Box - Scale/fade in, fade out on leave (exit), flip detection (boxSpringConfig). Under prefers-reduced-motion the panel jumps to position and skips the scale; the opacity fade remains
  • Date Pill - Slot machine-style number animation
  • Dots - Follow the crosshair spring; the core and halo spring open on hover

All animations use motion/react for fluid, natural movement.

<ChartTooltip
  indicatorDasharray="6,4"
  damping={60}
  indicatorColor="var(--chart-2)"
/>

Theming

The tooltip uses CSS variables for theming:

:root {
  --chart-background: oklch(1 0 0);
  --chart-crosshair: oklch(0.4 0.1828 274.34);
}

.dark {
  --chart-background: oklch(0.145 0 0);
  --chart-crosshair: oklch(0.45 0 0);
}

The tooltip box matches shadcn popovers: --chart-tooltip-background (default var(--popover)), --chart-tooltip-foreground (default var(--popover-foreground)), --chart-tooltip-muted (default var(--muted-foreground)), the theme border color, rounded-xl and a soft shadow-lg/5. Pass backgroundColor or panelStyle to override, e.g. for a translucent blurred panel.

To match the built-in header in custom content, use TooltipHeader:

<ChartTooltip
  content={({ point }) => (
    <>
      <TooltipHeader>{String(point.label)}</TooltipHeader>
      <div className="px-3.5 py-3 text-sm">…</div>
    </>
  )}
/>