From 114be9df07f2a7ad6b8fab236f4c378d4a90f556 Mon Sep 17 00:00:00 2001 From: Felipe Jacob Custodio Romero Date: Mon, 22 Jan 2024 22:27:03 +0100 Subject: [PATCH] [@mantine/charts] Add data formatter for legend and tooltip --- .../charts/src/AreaChart/AreaChart.tsx | 6 +- .../@mantine/charts/src/BarChart/BarChart.tsx | 6 +- .../charts/src/ChartLegend/ChartLegend.tsx | 27 ++++--- .../charts/src/ChartTooltip/ChartTooltip.tsx | 73 ++++++++++++++----- .../charts/src/LineChart/LineChart.tsx | 6 +- 5 files changed, 82 insertions(+), 36 deletions(-) diff --git a/packages/@mantine/charts/src/AreaChart/AreaChart.tsx b/packages/@mantine/charts/src/AreaChart/AreaChart.tsx index 88d7ddb08f..6ac95ada6c 100644 --- a/packages/@mantine/charts/src/AreaChart/AreaChart.tsx +++ b/packages/@mantine/charts/src/AreaChart/AreaChart.tsx @@ -315,13 +315,14 @@ export const AreaChart = factory((_props, ref) => { {withLegend && ( ( + content={({ payload }) => ( )} height={44} @@ -379,6 +380,7 @@ export const AreaChart = factory((_props, ref) => { unit={unit} classNames={resolvedClassNames} styles={resolvedStyles} + formatter={tooltipProps?.formatter} /> )} {...tooltipProps} diff --git a/packages/@mantine/charts/src/BarChart/BarChart.tsx b/packages/@mantine/charts/src/BarChart/BarChart.tsx index f7da22e936..d40e98dc19 100644 --- a/packages/@mantine/charts/src/BarChart/BarChart.tsx +++ b/packages/@mantine/charts/src/BarChart/BarChart.tsx @@ -223,13 +223,14 @@ export const BarChart = factory((_props, ref) => { {withLegend && ( ( + content={({ payload }) => ( )} height={44} @@ -288,6 +289,7 @@ export const BarChart = factory((_props, ref) => { unit={unit} classNames={resolvedClassNames} styles={resolvedStyles} + formatter={tooltipProps?.formatter} /> )} {...tooltipProps} diff --git a/packages/@mantine/charts/src/ChartLegend/ChartLegend.tsx b/packages/@mantine/charts/src/ChartLegend/ChartLegend.tsx index 26e2fda9e3..741845bd51 100644 --- a/packages/@mantine/charts/src/ChartLegend/ChartLegend.tsx +++ b/packages/@mantine/charts/src/ChartLegend/ChartLegend.tsx @@ -1,4 +1,5 @@ import React from 'react'; +import { Formatter, Payload } from 'recharts/types/component/DefaultLegendContent'; import { Box, BoxProps, @@ -12,7 +13,7 @@ import { } from '@mantine/core'; import classes from './ChartLegend.module.css'; -export function getFilteredChartLegendPayload(payload: Record[]) { +export function getFilteredChartLegendPayload(payload: Payload[]) { return payload.filter((item) => item.color !== 'none'); } @@ -22,9 +23,10 @@ export interface ChartLegendProps extends BoxProps, StylesApiProps, ElementProps<'div'> { - payload: Record[] | undefined; + payload: Payload[] | undefined; onHighlight: (area: string | null) => void; legendPosition: 'top' | 'bottom' | 'middle'; + formatter?: Formatter; } export type ChartLegendFactory = Factory<{ @@ -47,6 +49,7 @@ export const ChartLegend = factory((_props, ref) => { payload, onHighlight, legendPosition, + formatter, ...others } = props; @@ -71,16 +74,20 @@ export const ChartLegend = factory((_props, ref) => {
onHighlight(item.dataKey)} + onMouseEnter={() => onHighlight(item.value)} onMouseLeave={() => onHighlight(null)} > - -

{item.dataKey}

+ {item.color ? ( + + ) : undefined} +

+ {formatter ? formatter(item.value, item, index) : item.value} +

)); diff --git a/packages/@mantine/charts/src/ChartTooltip/ChartTooltip.tsx b/packages/@mantine/charts/src/ChartTooltip/ChartTooltip.tsx index ca35fbca8e..583cfa8669 100644 --- a/packages/@mantine/charts/src/ChartTooltip/ChartTooltip.tsx +++ b/packages/@mantine/charts/src/ChartTooltip/ChartTooltip.tsx @@ -1,4 +1,5 @@ import React from 'react'; +import { Formatter, Payload } from 'recharts/types/component/DefaultTooltipContent'; import { Box, BoxProps, @@ -12,7 +13,9 @@ import { } from '@mantine/core'; import classes from './ChartTooltip.module.css'; -export function getFilteredChartTooltipPayload(payload: Record[]) { +type MantinePayload = Payload & { fill?: string }; + +export function getFilteredChartTooltipPayload(payload: MantinePayload[]) { return payload.filter((item) => item.fill !== 'none'); } @@ -34,10 +37,13 @@ export interface ChartTooltipProps label?: React.ReactNode; /** Chart data provided by recharts */ - payload: Record[] | undefined; + payload: MantinePayload[] | undefined; /** Data units, provided by parent component */ unit?: string; + + /** Function used to format the display content */ + formatter?: Formatter; } export type ChartTooltipFactory = Factory<{ @@ -50,8 +56,19 @@ const defaultProps: Partial = {}; export const ChartTooltip = factory((_props, ref) => { const props = useProps('ChartTooltip', defaultProps, _props); - const { classNames, className, style, styles, unstyled, vars, payload, label, unit, ...others } = - props; + const { + classNames, + className, + style, + styles, + unstyled, + vars, + payload, + label, + unit, + formatter, + ...others + } = props; const getStyles = useStyles({ name: 'ChartTooltip', @@ -70,23 +87,39 @@ export const ChartTooltip = factory((_props, ref) => { const filteredPayload = getFilteredChartTooltipPayload(payload); - const items = filteredPayload.map((item) => ( -
-
- -
{item.name}
-
-
- {item.payload[item.dataKey]} - {unit} + const items = filteredPayload.map((item, index) => { + let finalValue: React.ReactNode | string = item.value; + let finalName: React.ReactNode | any = item.name; + + if (formatter !== undefined && item.value !== undefined) { + const formatted = formatter(item.value, item.name, item, index, payload); + if (Array.isArray(formatted)) { + [finalValue, finalName] = formatted; + } else { + finalValue = formatted; + } + } + + return ( +
+
+ {item.color ? ( + + ) : undefined} +
{finalName}
+
+
+ {finalValue} + {unit} +
-
- )); + ); + }); return ( diff --git a/packages/@mantine/charts/src/LineChart/LineChart.tsx b/packages/@mantine/charts/src/LineChart/LineChart.tsx index 82c8966ff5..611dafbea1 100644 --- a/packages/@mantine/charts/src/LineChart/LineChart.tsx +++ b/packages/@mantine/charts/src/LineChart/LineChart.tsx @@ -248,13 +248,14 @@ export const LineChart = factory((_props, ref) => { {withLegend && ( ( + content={({ payload }) => ( )} height={44} @@ -311,6 +312,7 @@ export const LineChart = factory((_props, ref) => { unit={unit} classNames={resolvedClassNames} styles={resolvedStyles} + formatter={tooltipProps?.formatter} /> )} {...tooltipProps}