Charts

Copy-paste chart examples for every Bklit UI component.

Sparkline - KPI cards

useSparklineHover drives the headline number: hover a sparkline to read any point, leave to fall back to the latest value.

function KpiCard({ label, data }) {  const hover = useSparklineHover<Point>();  const shown = hover.datum ?? data.at(-1);  return (    <div className="rounded-xl border p-4">      <span>{label}</span>      <span>{formatter.format(shown.value)}</span>      <AreaSparkline data={data} dataKey="value" height={40} {...hover.sparklineProps} />    </div>  );}const data = Array.from({ length: 24 }, (_, i) => ({  day: `Day ${i + 1}`,  value: Math.round(4200 + 40 * i + Math.sin(i * 0.7) * 500),}));

Line, area, and bar sparklines with a shared hover hook

Sparkline - Line

Fills its parent width; hover shows a dashed crosshair and dot.

<LineSparkline data={data} dataKey="value" height={56} />const data = Array.from({ length: 24 }, (_, i) => ({  day: `Day ${i + 1}`,  value: Math.round(4200 + 40 * i + Math.sin(i * 0.7) * 500),}));

Trending up by 5.2% this month

Sparkline - Area gradient

Area fill fades from the line to the baseline.

<AreaSparkline data={data} dataKey="value" height={56} />const data = Array.from({ length: 24 }, (_, i) => ({  day: `Day ${i + 1}`,  value: Math.round(4200 + 40 * i + Math.sin(i * 0.7) * 500),}));

Trending up by 5.2% this month

Sparkline - Area solid

Flat fill at a custom opacity.

<AreaSparkline  color="var(--chart-2)"  data={data}  dataKey="value"  fill="solid"  fillOpacity={0.2}  height={56}/>const data = Array.from({ length: 24 }, (_, i) => ({  day: `Day ${i + 1}`,  value: Math.round(4200 + 40 * i + Math.sin(i * 0.7) * 500),}));

Trending up by 5.2% this month

Sparkline - Bar

Rounded bars with a gap; non-hovered bars dim while hovering.

<BarSparkline  barGap={2}  barRadius={2}  color="var(--chart-3)"  data={data}  dataKey="value"  height={56}/>const data = Array.from({ length: 24 }, (_, i) => ({  day: `Day ${i + 1}`,  value: Math.round(4200 + 40 * i + Math.sin(i * 0.7) * 500),}));

Trending up by 5.2% this month

Sparkline - Negative bars

Bars grow from zero, so profit and loss read above and below the baseline.

const hover = useSparklineHover<Point>();const shown = hover.datum ?? data.at(-1);<span>{shown.day} · {shown.value}</span><BarSparkline data={data} dataKey="value" height={56} {...hover.sparklineProps} />const data = Array.from({ length: 20 }, (_, i) => ({  day: `Day ${i + 1}`,  value: Math.round(Math.sin(i * 0.9) * 420 + Math.cos(i * 2.3) * 180 + 40),}));

Trending up by 5.2% this month

Sparkline - Crosshair styles

Dashed (default), solid, and gradient hover guides.

<LineSparkline crosshair="dashed" data={data} dataKey="value" height={48} /><LineSparkline crosshair="solid" data={data} dataKey="value" height={48} /><LineSparkline crosshair="gradient" data={data} dataKey="value" height={48} />const data = Array.from({ length: 24 }, (_, i) => ({  day: `Day ${i + 1}`,  value: Math.round(4200 + 40 * i + Math.sin(i * 0.7) * 500),}));

Trending up by 5.2% this month

Sparkline - Hover feel

The crosshair and dot spring between points by default. Tune it with springConfig, or set hoverTransition={false} to snap.

<LineSparkline data={data} dataKey="value" height={48} /><LineSparkline  data={data}  dataKey="value"  height={48}  springConfig={{ stiffness: 600, damping: 45 }}/><LineSparkline data={data} dataKey="value" height={48} hoverTransition={false} />const data = Array.from({ length: 24 }, (_, i) => ({  day: `Day ${i + 1}`,  value: Math.round(4200 + 40 * i + Math.sin(i * 0.7) * 500),}));

Trending up by 5.2% this month

Sparkline - No spring

Synced area and bars with hoverTransition={false}: the crosshair and dot jump straight to each point, while the series fade and bar focus still animate.

const hover = useSparklineHover<Row>();<AreaSparkline  data={data}  dataKey="value"  hoverTransition={false}  {...hover.sparklineProps}/><BarSparkline  data={data}  dataKey="value"  hoverTransition={false}  {...hover.sparklineProps}/>const data = Array.from({ length: 24 }, (_, i) => ({  day: `Day ${i + 1}`,  value: Math.round(4200 + 40 * i + Math.sin(i * 0.7) * 500),}));

Trending up by 5.2% this month

Sparkline - End dot

Static trend next to a stat: endDot marks the latest value and interactive={false} skips pointer tracking.

<LineSparkline  color="var(--chart-4)"  curve="natural"  data={data}  dataKey="value"  endDot  height={40}  interactive={false}/>const data = Array.from({ length: 24 }, (_, i) => ({  day: `Day ${i + 1}`,  value: Math.round(4200 + 40 * i + Math.sin(i * 0.7) * 500),}));

Trending up by 5.2% this month

Sparkline - Step

Step curve for discrete levels (seats, plan tiers), anchored at zero with yDomain.

<AreaSparkline  color="var(--chart-5)"  curve="step"  data={data}  dataKey="value"  endDot  height={56}  yDomain={[0]}/>const data = [5, 5, 5, 8, 8, 8, 8, 12, 12, 10, 10, 15, 15, 15, 20, 20, 18, 25]  .map((value, i) => ({ day: `Week ${i + 1}`, value }));

Trending up by 5.2% this month

Sparkline - Synced hover

One useSparklineHover shared by every row: hovering any sparkline moves them all.

const hover = useSparklineHover();{series.map((s) => (  <div key={s.label}>    <span>{s.label}</span>    <LineSparkline      color={s.color}      data={s.data}      dataKey="value"      height={28}      {...hover.sparklineProps}    />    <span>{s.data[hover.index ?? s.data.length - 1].value}</span>  </div>))}const data = Array.from({ length: 24 }, (_, i) => ({  day: `Day ${i + 1}`,  value: Math.round(4200 + 40 * i + Math.sin(i * 0.7) * 500),}));

Trending up by 5.2% this month

Sparkline - Table

Fixed-width sparklines inline in a table, coloured by direction.

<td>  <LineSparkline    color={change >= 0 ? "var(--chart-positive)" : "var(--chart-negative)"}    data={row.data}    dataKey="value"    height={24}    strokeWidth={1.5}    width={120}  /></td>const data = Array.from({ length: 24 }, (_, i) => ({  day: `Day ${i + 1}`,  value: Math.round(4200 + 40 * i + Math.sin(i * 0.7) * 500),}));

Trending up by 5.2% this month

Sparkline - Dense grid

64 sparklines sharing a single ResizeObserver, with no per-instance animation runtime.

{series.map((data, i) => {  const Component = [AreaSparkline, LineSparkline, BarSparkline][i % 3];  return (    <Component      color={`var(--chart-${(i % 5) + 1})`}      data={data}      dataKey="value"      height={24}      key={i}    />  );})}

Trending up by 5.2% this month