diff --git a/packages/@mantine/charts/src/DonutChart/DonutChart.story.tsx b/packages/@mantine/charts/src/DonutChart/DonutChart.story.tsx
index 38d6142246..5abfb0b909 100644
--- a/packages/@mantine/charts/src/DonutChart/DonutChart.story.tsx
+++ b/packages/@mantine/charts/src/DonutChart/DonutChart.story.tsx
@@ -12,7 +12,13 @@ const data = [
export function Usage() {
return (
-
+
);
}
diff --git a/packages/@mantine/charts/src/DonutChart/DonutChart.tsx b/packages/@mantine/charts/src/DonutChart/DonutChart.tsx
index f0ec6a2316..7cc7e53e14 100644
--- a/packages/@mantine/charts/src/DonutChart/DonutChart.tsx
+++ b/packages/@mantine/charts/src/DonutChart/DonutChart.tsx
@@ -1,5 +1,7 @@
+import React, { useState } from 'react';
import {
Cell,
+ Legend,
Pie,
PieLabel,
PieProps,
@@ -75,9 +77,12 @@ export interface DonutChartProps
/** Controls thickness of the chart segments, `20` by default */
thickness?: number;
- /** Controls chart width and height, height is increased by 40 if `withLabels` prop is set. Cannot be less than `thickness`. `80` by default */
+ /** Controls chart area size along with side legend */
size?: number;
+ /** Controls chart width and height, height is increased by 40 if `withLabels` prop is set. Cannot be less than `thickness`. `80` by default */
+ pieSize?: number;
+
/** Controls width of segments stroke, `1` by default */
strokeWidth?: number;
@@ -104,6 +109,20 @@ export interface DonutChartProps
/** A function to format values inside the tooltip */
valueFormatter?: (value: number) => string;
+
+ /** Defines the behavior of the legend. Can be 'hover' (hover to highlight segments) or 'side' (static side legend). */
+ legendMode?: 'hover' | 'side';
+
+ /** Specifies the position of the legend on the chart. */
+ legendOrientation?:
+ | 'top'
+ | 'bottom'
+ | 'top-left'
+ | 'top-right'
+ | 'bottom-left'
+ | 'bottom-right'
+ | 'center-left'
+ | 'center-right';
}
export type DonutChartFactory = Factory<{
@@ -118,7 +137,8 @@ const defaultProps: Partial = {
withLabelsLine: true,
paddingAngle: 0,
thickness: 20,
- size: 160,
+ size: 240,
+ pieSize: 160,
strokeWidth: 1,
startAngle: 0,
endAngle: 360,
@@ -188,6 +208,7 @@ export const DonutChart = factory((_props, ref) => {
withLabels,
withLabelsLine,
size,
+ pieSize,
thickness,
strokeWidth,
startAngle,
@@ -199,10 +220,13 @@ export const DonutChart = factory((_props, ref) => {
valueFormatter,
strokeColor,
labelsType,
+ legendMode,
+ legendOrientation,
...others
} = props;
const theme = useMantineTheme();
+ const [hoveredSegment, setHoveredSegment] = useState(null);
const getStyles = useStyles({
name: 'DonutChart',
@@ -229,17 +253,37 @@ export const DonutChart = factory((_props, ref) => {
fill={getThemeColor(item.color, theme)}
stroke="var(--chart-stroke-color, var(--mantine-color-body))"
strokeWidth={strokeWidth}
+ fillOpacity={
+ legendMode === 'side' && hoveredSegment !== null
+ ? hoveredSegment === item.name
+ ? 1
+ : 0.5
+ : 1
+ }
/>
));
+ const legendPosition = {
+ top: { x: 0, y: -180 },
+ bottom: { x: 0, y: 180 },
+ 'top-left': { x: -180, y: -180 },
+ 'top-right': { x: 180, y: -180 },
+ 'bottom-left': { x: -180, y: 180 },
+ 'bottom-right': { x: 180, y: 180 },
+ 'center-left': { x: -230, y: 0 },
+ 'center-right': { x: 230, y: 0 },
+ };
+
+ const legendOffset = { x: 260, y: legendPosition[legendOrientation || 'center-right'].y };
+
return (
((_props, ref) => {
)}
- {withTooltip && (
+ {legendMode === 'hover' && withTooltip && (
((_props, ref) => {
valueFormatter={valueFormatter}
/>
)}
+ position={{ x: legendOffset.x, y: legendOffset.y }}
{...tooltipProps}
/>
)}
+ {legendMode === 'side' && (
+