From ad3b494b73fae3c7780460359d046584452a54bc Mon Sep 17 00:00:00 2001 From: Jose Quintas Date: Fri, 12 Jun 2026 12:17:34 +0200 Subject: [PATCH 1/4] [charts] Apply axis colorMap to radial bar fill The radialBar color processor was defined but never invoked, so a colorMap on the rotation or radius axis was ignored and every bar used the series color. Call the processor in useRadialBarPlotData, mirroring BarChart, so the band axis colorMap colors each bar. Add a 'Coloring each bar' docs section with a health dashboard demo. --- .../radial-bars/HealthRadialBarChart.js | 60 +++++++++++++++++++ .../radial-bars/HealthRadialBarChart.tsx | 60 +++++++++++++++++++ docs/data/charts/radial-bars/radial-bars.md | 9 +++ .../RadialBarChart/useRadialBarPlotData.ts | 5 +- 4 files changed, 133 insertions(+), 1 deletion(-) create mode 100644 docs/data/charts/radial-bars/HealthRadialBarChart.js create mode 100644 docs/data/charts/radial-bars/HealthRadialBarChart.tsx diff --git a/docs/data/charts/radial-bars/HealthRadialBarChart.js b/docs/data/charts/radial-bars/HealthRadialBarChart.js new file mode 100644 index 0000000000000..dcd87eebe3000 --- /dev/null +++ b/docs/data/charts/radial-bars/HealthRadialBarChart.js @@ -0,0 +1,60 @@ +import * as React from 'react'; +import { RadialBarChart } from '@mui/x-charts-premium/RadialBarChart'; + +const healthData = [ + { metric: 'Water', value: 5, goal: 8, color: '#00bcd4' }, + { metric: 'Sleep', value: 6.5, goal: 8, color: '#3f51b5' }, + { metric: 'Calories', value: 540, goal: 700, color: '#ff9800' }, + { metric: 'Activity', value: 42, goal: 60, color: '#4caf50' }, + { metric: 'Steps', value: 8200, goal: 10000, color: '#e91e63' }, +]; + +const dataset = healthData.map((d) => ({ + metric: d.metric, + progress: Math.round((d.value / d.goal) * 100), +})); + +const highlightScope = { highlight: 'item', fade: 'global' }; + +export default function HealthRadialBarChart() { + return ( + `${value}%`, + }, + ]} + radiusAxis={[ + { + scaleType: 'band', + dataKey: 'metric', + categoryGapRatio: 0.3, + disableLine: true, + disableTicks: true, + colorMap: { + type: 'ordinal', + values: healthData.map((d) => d.metric), + colors: healthData.map((d) => d.color), + }, + }, + ]} + rotationAxis={[ + { + scaleType: 'linear', + min: 0, + max: 100, + valueFormatter: (value) => `${value}%`, + }, + ]} + grid={{ rotation: true }} + hideLegend + slotProps={{ tooltip: { trigger: 'none' } }} + /> + ); +} diff --git a/docs/data/charts/radial-bars/HealthRadialBarChart.tsx b/docs/data/charts/radial-bars/HealthRadialBarChart.tsx new file mode 100644 index 0000000000000..a364297739e50 --- /dev/null +++ b/docs/data/charts/radial-bars/HealthRadialBarChart.tsx @@ -0,0 +1,60 @@ +import * as React from 'react'; +import { RadialBarChart } from '@mui/x-charts-premium/RadialBarChart'; + +const healthData = [ + { metric: 'Water', value: 5, goal: 8, color: '#00bcd4' }, + { metric: 'Sleep', value: 6.5, goal: 8, color: '#3f51b5' }, + { metric: 'Calories', value: 540, goal: 700, color: '#ff9800' }, + { metric: 'Activity', value: 42, goal: 60, color: '#4caf50' }, + { metric: 'Steps', value: 8200, goal: 10000, color: '#e91e63' }, +]; + +const dataset = healthData.map((d) => ({ + metric: d.metric, + progress: Math.round((d.value / d.goal) * 100), +})); + +const highlightScope = { highlight: 'item', fade: 'global' } as const; + +export default function HealthRadialBarChart() { + return ( + `${value}%`, + }, + ]} + radiusAxis={[ + { + scaleType: 'band', + dataKey: 'metric', + categoryGapRatio: 0.3, + disableLine: true, + disableTicks: true, + colorMap: { + type: 'ordinal', + values: healthData.map((d) => d.metric), + colors: healthData.map((d) => d.color), + }, + }, + ]} + rotationAxis={[ + { + scaleType: 'linear', + min: 0, + max: 100, + valueFormatter: (value) => `${value}%`, + }, + ]} + grid={{ rotation: true }} + hideLegend + slotProps={{ tooltip: { trigger: 'none' } }} + /> + ); +} diff --git a/docs/data/charts/radial-bars/radial-bars.md b/docs/data/charts/radial-bars/radial-bars.md index 011ab075fb0dc..6f420c61ccff8 100644 --- a/docs/data/charts/radial-bars/radial-bars.md +++ b/docs/data/charts/radial-bars/radial-bars.md @@ -27,6 +27,15 @@ The demo below demonstrates those options. {{"demo": "RadialBarConfig.js", "hideToolbar": true, "bg": "playground"}} +## Coloring each bar + +Set a `colorMap` on the band axis to give each category its own color. +With `layout='horizontal'` the band categories sit on the `radiusAxis`, so an `'ordinal'` color map there paints each concentric ring independently. + +The demo below uses this to build a health dashboard where every metric ring tracks progress toward its goal. + +{{"demo": "HealthRadialBarChart.js", "bg": "outline"}} + ## Click events The `RadialBarChart` provides an `onAxisClick` handler that fires when the user clicks anywhere in the chart area. diff --git a/packages/x-charts-premium/src/RadialBarChart/useRadialBarPlotData.ts b/packages/x-charts-premium/src/RadialBarChart/useRadialBarPlotData.ts index e74af8e4838c2..030a482f97414 100644 --- a/packages/x-charts-premium/src/RadialBarChart/useRadialBarPlotData.ts +++ b/packages/x-charts-premium/src/RadialBarChart/useRadialBarPlotData.ts @@ -15,6 +15,7 @@ import { type ChartsRadialAxisProps, } from '@mui/x-charts/internals'; import { type SeriesId } from '@mui/x-charts/models'; +import getColor from './seriesConfig/getColor'; interface ProcessedRadialBarData { seriesId: SeriesId; @@ -102,6 +103,8 @@ function processRadialBarDataForPlot( const rotationOrigin = rotationAxisConfig.scale(0) ?? 0; const radiusOrigin = radiusAxisConfig.scale(0) ?? 0; + const colorGetter = getColor(seriesItem, rotationAxisConfig, radiusAxisConfig); + const { barWidth: bandSlice, offset } = getBandSize( baseScale.bandwidth(), stackingGroups.length, @@ -138,7 +141,7 @@ function processRadialBarDataForPlot( seriesId, dataIndex, hidden: seriesItem.hidden, - color: seriesItem.color, + color: colorGetter(dataIndex), value: seriesValue, startAngle: verticalLayout ? baseStart : valueStart, endAngle: verticalLayout ? baseEnd : valueEnd, From 33a8210dea42762424bd39ab5ee01367736cd75a Mon Sep 17 00:00:00 2001 From: Jose Quintas Date: Fri, 12 Jun 2026 13:42:06 +0200 Subject: [PATCH 2/4] ci: retrigger static From 378852654fe11faa0dbf91e132bf0e2ea8f2eb51 Mon Sep 17 00:00:00 2001 From: Jose Quintas Date: Wed, 17 Jun 2026 14:35:05 +0200 Subject: [PATCH 3/4] improve --- docs/data/charts/radial-bars/HealthRadialBarChart.js | 7 +++++-- docs/data/charts/radial-bars/HealthRadialBarChart.tsx | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/docs/data/charts/radial-bars/HealthRadialBarChart.js b/docs/data/charts/radial-bars/HealthRadialBarChart.js index dcd87eebe3000..208f78c539953 100644 --- a/docs/data/charts/radial-bars/HealthRadialBarChart.js +++ b/docs/data/charts/radial-bars/HealthRadialBarChart.js @@ -14,7 +14,7 @@ const dataset = healthData.map((d) => ({ progress: Math.round((d.value / d.goal) * 100), })); -const highlightScope = { highlight: 'item', fade: 'global' }; +const highlightScope = { highlight: 'none', fade: 'none' }; export default function HealthRadialBarChart() { return ( @@ -47,12 +47,15 @@ export default function HealthRadialBarChart() { rotationAxis={[ { scaleType: 'linear', + disableTickLabel: true, + disableLine: true, + disableTicks: true, min: 0, max: 100, valueFormatter: (value) => `${value}%`, }, ]} - grid={{ rotation: true }} + axisHighlight={{ rotation: 'none', radius: 'none' }} hideLegend slotProps={{ tooltip: { trigger: 'none' } }} /> diff --git a/docs/data/charts/radial-bars/HealthRadialBarChart.tsx b/docs/data/charts/radial-bars/HealthRadialBarChart.tsx index a364297739e50..3ba9d32cdcdaa 100644 --- a/docs/data/charts/radial-bars/HealthRadialBarChart.tsx +++ b/docs/data/charts/radial-bars/HealthRadialBarChart.tsx @@ -14,7 +14,7 @@ const dataset = healthData.map((d) => ({ progress: Math.round((d.value / d.goal) * 100), })); -const highlightScope = { highlight: 'item', fade: 'global' } as const; +const highlightScope = { highlight: 'none', fade: 'none' } as const; export default function HealthRadialBarChart() { return ( @@ -47,12 +47,15 @@ export default function HealthRadialBarChart() { rotationAxis={[ { scaleType: 'linear', + disableTickLabel: true, + disableLine: true, + disableTicks: true, min: 0, max: 100, valueFormatter: (value) => `${value}%`, }, ]} - grid={{ rotation: true }} + axisHighlight={{ rotation: 'none', radius: 'none' }} hideLegend slotProps={{ tooltip: { trigger: 'none' } }} /> From a2196f3baea7ad2be5dd6c28b5201f448a0fab6d Mon Sep 17 00:00:00 2001 From: Jose Quintas Date: Fri, 19 Jun 2026 10:44:30 +0200 Subject: [PATCH 4/4] doc suggestion --- docs/data/charts/radial-bars/radial-bars.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/data/charts/radial-bars/radial-bars.md b/docs/data/charts/radial-bars/radial-bars.md index ab5ac8f0797d1..b1710dcf882ac 100644 --- a/docs/data/charts/radial-bars/radial-bars.md +++ b/docs/data/charts/radial-bars/radial-bars.md @@ -38,10 +38,10 @@ The demo below demonstrates those options. ## Coloring each bar -Set a `colorMap` on the band axis to give each category its own color. -With `layout='horizontal'` the band categories sit on the `radiusAxis`, so an `'ordinal'` color map there paints each concentric ring independently. +Radial bars support the same [color scale](/x/react-charts/bars/#color-scale) as the bar chart. +The only difference is that the cartesian `x` and `y` axes are replaced by the `rotationAxis` and `radiusAxis`, so you can set a `colorMap` on either of them. -The demo below uses this to build a health dashboard where every metric ring tracks progress toward its goal. +The demo below sets an `'ordinal'` color map on the `radiusAxis` to build a health dashboard where every metric ring tracks progress toward its goal. {{"demo": "HealthRadialBarChart.js", "bg": "outline"}}