diff --git a/packages/@mantine/charts/src/DonutChart/DonutChart.tsx b/packages/@mantine/charts/src/DonutChart/DonutChart.tsx index dd8279b058e..f0ec6a2316e 100644 --- a/packages/@mantine/charts/src/DonutChart/DonutChart.tsx +++ b/packages/@mantine/charts/src/DonutChart/DonutChart.tsx @@ -1,6 +1,7 @@ import { Cell, Pie, + PieLabel, PieProps, PieChart as ReChartsPieChart, ResponsiveContainer, @@ -98,6 +99,9 @@ export interface DonutChartProps /** Props passed down to recharts `PieChart` component */ pieChartProps?: React.ComponentPropsWithoutRef; + /** Type of labels to display, `'value'` by default */ + labelsType?: 'value' | 'percent'; + /** A function to format values inside the tooltip */ valueFormatter?: (value: number) => string; } @@ -118,6 +122,7 @@ const defaultProps: Partial = { strokeWidth: 1, startAngle: 0, endAngle: 360, + labelsType: 'value', tooltipDataSource: 'all', }; @@ -131,6 +136,40 @@ const varsResolver = createVarsResolver( }) ); +const getLabelValue = ( + labelsType: DonutChartProps['labelsType'], + value: number, + percent: number, + valueFormatter?: DonutChartProps['valueFormatter'] +) => { + if (labelsType === 'percent') { + return `${(percent * 100).toFixed(0)}%`; + } + + if (typeof valueFormatter === 'function') { + return valueFormatter(value); + } + + return value; +}; + +const getLabel = + (labelsType: 'value' | 'percent', valueFormatter?: DonutChartProps['valueFormatter']): PieLabel => + ({ x, y, cx, cy, percent, value }) => ( + cx ? 'start' : 'end'} + fill="var(--chart-labels-color, var(--mantine-color-dimmed))" + fontFamily="var(--mantine-font-family)" + fontSize={12} + > + {getLabelValue(labelsType, value, percent, valueFormatter)} + + ); + export const DonutChart = factory((_props, ref) => { const props = useProps('DonutChart', defaultProps, _props); const { @@ -159,6 +198,7 @@ export const DonutChart = factory((_props, ref) => { pieChartProps, valueFormatter, strokeColor, + labelsType, ...others } = props; @@ -205,15 +245,7 @@ export const DonutChart = factory((_props, ref) => { paddingAngle={paddingAngle} startAngle={startAngle} endAngle={endAngle} - label={ - withLabels - ? { - fill: 'var(--chart-labels-color, var(--mantine-color-dimmed))', - fontSize: 12, - fontFamily: 'var(--mantine-font-family)', - } - : false - } + label={withLabels ? getLabel(labelsType || 'value', valueFormatter) : false} labelLine={ withLabelsLine ? {