Skip to content

Commit 14fb66f

Browse files
Fix chart tooltip typings
1 parent e727393 commit 14fb66f

File tree

1 file changed

+36
-18
lines changed

1 file changed

+36
-18
lines changed

src/components/ui/chart.tsx

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ import * as React from "react";
44
import * as RechartsPrimitive from "recharts";
55
import type { LegendPayload } from "recharts/types/component/DefaultLegendContent";
66
import {
7+
Formatter,
78
NameType,
8-
Payload,
99
ValueType,
1010
} from "recharts/types/component/DefaultTooltipContent";
1111
import type { Props as LegendProps } from "recharts/types/component/Legend";
@@ -38,16 +38,10 @@ export type CustomTooltipProps = TooltipContentProps<ValueType, NameType> & {
3838
nameKey?: string;
3939
labelKey?: string;
4040
labelFormatter?: (
41-
label: TooltipContentProps<number, string>["label"],
42-
payload: TooltipContentProps<number, string>["payload"],
43-
) => React.ReactNode;
44-
formatter?: (
45-
value: number | string,
46-
name: string,
47-
item: Payload<number | string, string>,
48-
index: number,
49-
payload: ReadonlyArray<Payload<number | string, string>>,
41+
label: TooltipContentProps<ValueType, NameType>["label"],
42+
payload: TooltipContentProps<ValueType, NameType>["payload"],
5043
) => React.ReactNode;
44+
formatter?: Formatter<ValueType, NameType>;
5145
labelClassName?: string;
5246
color?: string;
5347
};
@@ -215,20 +209,23 @@ function ChartTooltipContent({
215209
{!nestLabel ? tooltipLabel : null}
216210
<div className="grid gap-1.5">
217211
{payload.map((item, index) => {
218-
const key = `${nameKey || item.name || item.dataKey || "value"}`;
212+
const key = `${nameKey || item.name || dataKeyToString(item.dataKey) || "value"}`;
219213
const itemConfig = getPayloadConfigFromPayload(config, item, key);
220214
const indicatorColor = color || item.payload.fill || item.color;
215+
const itemKey = getTooltipItemKey(item, index);
221216

222217
return (
223218
<div
224-
key={item.dataKey}
219+
key={itemKey}
225220
className={cn(
226221
"[&>svg]:text-muted-foreground flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5",
227222
indicator === "dot" && "items-center",
228223
)}
229224
>
230-
{formatter && item?.value !== undefined && item.name ? (
231-
formatter(item.value, item.name, item, index, item.payload)
225+
{formatter &&
226+
item.value !== undefined &&
227+
item.name !== undefined ? (
228+
formatter(item.value, item.name, item, index, payload)
232229
) : (
233230
<>
234231
{itemConfig?.icon ? (
@@ -267,9 +264,9 @@ function ChartTooltipContent({
267264
{itemConfig?.label || item.name}
268265
</span>
269266
</div>
270-
{item.value && (
267+
{item.value !== undefined && (
271268
<span className="text-foreground font-mono font-medium tabular-nums">
272-
{item.value.toLocaleString()}
269+
{formatTooltipValue(item.value)}
273270
</span>
274271
)}
275272
</div>
@@ -283,6 +280,27 @@ function ChartTooltipContent({
283280
);
284281
}
285282

283+
function dataKeyToString(dataKey: unknown): string | undefined {
284+
return typeof dataKey === "string" || typeof dataKey === "number"
285+
? String(dataKey)
286+
: undefined;
287+
}
288+
289+
function getTooltipItemKey(
290+
item: TooltipContentProps<ValueType, NameType>["payload"][number],
291+
index: number,
292+
): React.Key {
293+
return dataKeyToString(item.dataKey) ?? item.name ?? index;
294+
}
295+
296+
function formatTooltipValue(value: ValueType): string {
297+
if (Array.isArray(value)) {
298+
return value.map((entry) => entry.toLocaleString()).join(" - ");
299+
}
300+
301+
return value.toLocaleString();
302+
}
303+
286304
const ChartLegend = RechartsPrimitive.Legend;
287305

288306
function ChartLegendContent({
@@ -376,9 +394,9 @@ function getPayloadConfigFromPayload(
376394

377395
export {
378396
ChartContainer,
379-
ChartTooltip,
380-
ChartTooltipContent,
381397
ChartLegend,
382398
ChartLegendContent,
383399
ChartStyle,
400+
ChartTooltip,
401+
ChartTooltipContent,
384402
};

0 commit comments

Comments
 (0)