Skip to content
design
Components

Chart tooltip

Inspect chart observations with registry labels and caller-formatted values by pointer or keyboard.

On this page
  • Illustrative amount
Day
Illustrative amount
Mon
2
Tue
4
Wed
3
Thu
6
Inspect chart observations with registry labels and caller-formatted values by pointer or keyboard.
Code
import { ChartContainer, type ChartRegistry } from "@bosunkit/components/chart-container";
import { ChartTooltip } from "@bosunkit/components/chart-tooltip";
import { ChartLegend } from "@bosunkit/components/chart-legend";
import { DataTable, type Column } from "@bosunkit/components/data-table";
import * as Recharts from "recharts";
import type { ReactElement } from "react";

export const description: string =
  "A custom Recharts area uses the same registry, token colors and formatted tooltip as the standard charts.";
const values: Readonly<Record<number, string>> = {
  0: "0",
  1: "1",
  2: "2",
  3: "3",
  4: "4",
  5: "5",
  6: "6",
  7: "7",
  8: "8",
};
const formatValue: (value: number) => string = (value: number): string => values[value] ?? "";
const formatCategory: (value: string | number) => string = (value: string | number): string =>
  typeof value === "string" ? value : "";
const config: ChartRegistry = { amount: { label: "Illustrative amount", formatValue, color: "03" } };
const data: { day: string; amount: number | null }[] = [
  { day: "Mon", amount: 2 },
  { day: "Tue", amount: 4 },
  { day: "Wed", amount: 3 },
  { day: "Thu", amount: 6 },
];
const columns: readonly Column[] = [
  { key: "day", label: "Day" },
  {
    key: "amount",
    label: "Illustrative amount",
    align: "end",
    render: (row: Record<string, unknown>): string => {
      const { amount }: Record<string, unknown> = row;
      return typeof amount === "number" ? formatValue(amount) : "Not counted";
    },
  },
];

export default function ComposedArea(): ReactElement {
  return (
    <div>
      <ChartContainer
        config={config}
        label="Illustrative daily amounts"
        formatCategory={formatCategory}
        missingValueText="Not counted"
      >
        <Recharts.AreaChart data={data} accessibilityLayer aria-label="Illustrative daily amounts">
          <Recharts.CartesianGrid vertical={false} />
          <Recharts.XAxis dataKey="day" tickFormatter={formatCategory} axisLine={false} tickLine={false} />
          <Recharts.YAxis domain={[0, 8]} tickFormatter={formatValue} axisLine={false} tickLine={false} width="auto" />
          <Recharts.Area
            dataKey="amount"
            type="linear"
            stroke="var(--color-amount)"
            fill="var(--color-amount)"
            fillOpacity={0.2}
            isAnimationActive={false}
            connectNulls={false}
          />
          <ChartTooltip />
        </Recharts.AreaChart>
      </ChartContainer>
      <ChartLegend config={config} label="Amount series" />
      <section aria-label="Illustrative source values">
        <DataTable columns={columns} rows={data} />
      </section>
    </div>
  );
}

The chart tooltip installs formatted content into Recharts inspection. It reads the registry, selected keys, category formatter and missing-value text from ChartContainer, or accepts them explicitly. It never falls back to locale-independent number strings.

01One series definitionNames, palette slots and patterns come from the same registry used by the drawing.
02Caller-formatted valuesThe caller supplies display text and quantity formatters; missing values have an explicit description.
03Accessible inspectionNames and patterns supplement color, and analytical plots expose their observations in a source table.

The tooltip also resolves pie categories from their registry keys. Typed interval definitions add caller-formatted bounds under the associated series; unavailable bounds retain the missing-value description.

Use

Each row uses the series' registry name, color and pattern. Zero is an observation; missing values use the caller's text. Category headings state the time reference when they are times. Keyboard inspection remains enabled on the chart root. A source table makes the values available without hover, including categories whose observations are all missing.

shared={false} inspects one hovered mark on Recharts roots that support item inspection, including BarChart. It omits the shared axis cursor, shows only that mark's registry entry and allows the tooltip to extend vertically beyond a compact plot. The error breakdown uses this mode with an active segment outline and caller-formatted counts and percentages. Leaving shared unset uses the chart root's default, including shared inspection for line charts.

Examples

Composition

  • Illustrative amount
Day
Illustrative amount
Mon
2
Tue
4
Wed
3
Thu
6
A custom Recharts area uses the same registry, token colors and formatted tooltip as the standard charts.
Code
import { ChartContainer, type ChartRegistry } from "@bosunkit/components/chart-container";
import { ChartTooltip } from "@bosunkit/components/chart-tooltip";
import { ChartLegend } from "@bosunkit/components/chart-legend";
import { DataTable, type Column } from "@bosunkit/components/data-table";
import * as Recharts from "recharts";
import type { ReactElement } from "react";

export const description: string =
  "A custom Recharts area uses the same registry, token colors and formatted tooltip as the standard charts.";
const values: Readonly<Record<number, string>> = {
  0: "0",
  1: "1",
  2: "2",
  3: "3",
  4: "4",
  5: "5",
  6: "6",
  7: "7",
  8: "8",
};
const formatValue: (value: number) => string = (value: number): string => values[value] ?? "";
const formatCategory: (value: string | number) => string = (value: string | number): string =>
  typeof value === "string" ? value : "";
const config: ChartRegistry = { amount: { label: "Illustrative amount", formatValue, color: "03" } };
const data: { day: string; amount: number | null }[] = [
  { day: "Mon", amount: 2 },
  { day: "Tue", amount: 4 },
  { day: "Wed", amount: 3 },
  { day: "Thu", amount: 6 },
];
const columns: readonly Column[] = [
  { key: "day", label: "Day" },
  {
    key: "amount",
    label: "Illustrative amount",
    align: "end",
    render: (row: Record<string, unknown>): string => {
      const { amount }: Record<string, unknown> = row;
      return typeof amount === "number" ? formatValue(amount) : "Not counted";
    },
  },
];

export default function ComposedArea(): ReactElement {
  return (
    <div>
      <ChartContainer
        config={config}
        label="Illustrative daily amounts"
        formatCategory={formatCategory}
        missingValueText="Not counted"
      >
        <Recharts.AreaChart data={data} accessibilityLayer aria-label="Illustrative daily amounts">
          <Recharts.CartesianGrid vertical={false} />
          <Recharts.XAxis dataKey="day" tickFormatter={formatCategory} axisLine={false} tickLine={false} />
          <Recharts.YAxis domain={[0, 8]} tickFormatter={formatValue} axisLine={false} tickLine={false} width="auto" />
          <Recharts.Area
            dataKey="amount"
            type="linear"
            stroke="var(--color-amount)"
            fill="var(--color-amount)"
            fillOpacity={0.2}
            isAnimationActive={false}
            connectNulls={false}
          />
          <ChartTooltip />
        </Recharts.AreaChart>
      </ChartContainer>
      <ChartLegend config={config} label="Amount series" />
      <section aria-label="Illustrative source values">
        <DataTable columns={columns} rows={data} />
      </section>
    </div>
  );
}

Props

PropTypeDefaultDescription
sharedboolean | undefined–Inspect all series at an axis position when true, or individual marks when false; unset follows the Recharts root's default.
configChartRegistry | undefined–The registry; inherited from ChartContainer when unset.
seriesreadonly string[] | undefined–Series in display order; inherited from ChartContainer when unset.
bandsreadonly ChartBandDefinition[] | undefined–Intervals displayed under their associated series; inherited from ChartContainer when unset.
formatCategory((value: string | number) => string) | undefined–Writes the category or time with its reference; inherited from ChartContainer when unset.
missingValueTextstring | undefined–Display text for a missing value; inherited from ChartContainer when unset.
testIdstring | undefined–Becomes data-testid on the visible tooltip content.
Do
  • Illustrative amount
Day
Illustrative amount
Mon
2
Tue
4
Wed
3
Thu
6
Name the observations and keep the comparison basis visible.
Don't

Keep a gap and describe the missing measurement in the source table.

A missing observation must not appear to be zero.
  • Data visualization: scales, missing measurements and comparable evidence.
  • Chart panel: titles, controls and source information.
  • Sparkline: compact trends with operational integrity and forecast information.