diff --git a/docs/data/charts/funnel/FunnelDataAttributes.js b/docs/data/charts/funnel/FunnelDataAttributes.js
new file mode 100644
index 0000000000000..33505c0af80c9
--- /dev/null
+++ b/docs/data/charts/funnel/FunnelDataAttributes.js
@@ -0,0 +1,40 @@
+import * as React from 'react';
+import Box from '@mui/material/Box';
+import {
+ Unstable_FunnelChart as FunnelChart,
+ funnelSectionClasses,
+} from '@mui/x-charts-pro/FunnelChart';
+
+export default function FunnelDataAttributes() {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+const funnelProps = {
+ height: 300,
+ hideLegend: true,
+ series: [
+ {
+ id: 'main',
+ data: [{ value: 200 }, { value: 180 }, { value: 90 }, { value: 50 }],
+ },
+ ],
+};
diff --git a/docs/data/charts/funnel/FunnelDataAttributes.tsx b/docs/data/charts/funnel/FunnelDataAttributes.tsx
new file mode 100644
index 0000000000000..4c9d77a94cf72
--- /dev/null
+++ b/docs/data/charts/funnel/FunnelDataAttributes.tsx
@@ -0,0 +1,40 @@
+import * as React from 'react';
+import Box from '@mui/material/Box';
+import {
+ Unstable_FunnelChart as FunnelChart,
+ funnelSectionClasses,
+} from '@mui/x-charts-pro/FunnelChart';
+
+export default function FunnelDataAttributes() {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+const funnelProps = {
+ height: 300,
+ hideLegend: true,
+ series: [
+ {
+ id: 'main',
+ data: [{ value: 200 }, { value: 180 }, { value: 90 }, { value: 50 }],
+ },
+ ],
+} as const;
diff --git a/docs/data/charts/funnel/FunnelDataAttributes.tsx.preview b/docs/data/charts/funnel/FunnelDataAttributes.tsx.preview
new file mode 100644
index 0000000000000..846f54b1dadb8
--- /dev/null
+++ b/docs/data/charts/funnel/FunnelDataAttributes.tsx.preview
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/data/charts/funnel/funnel.md b/docs/data/charts/funnel/funnel.md
index 6d1c173fadeab..2ff49cc937352 100644
--- a/docs/data/charts/funnel/funnel.md
+++ b/docs/data/charts/funnel/funnel.md
@@ -123,6 +123,16 @@ The funnel colors can be customized in two ways.
{{"demo": "FunnelColor.js"}}
+### CSS
+
+The funnel chart can be styled using CSS.
+
+Each section group has a `data-series` attribute that can be used to target specific series sections.
+
+In order to target specific sections, you can use the `:nth-child` or `:nth-child-of-type` selectors as shown in the example below.
+
+{{"demo": "FunnelDataAttributes.js"}}
+
## Multiple funnels
By default, multiple series are displayed on top of each other.
diff --git a/packages/x-charts-pro/src/FunnelChart/FunnelPlot.tsx b/packages/x-charts-pro/src/FunnelChart/FunnelPlot.tsx
index c3266ea4c1e85..e173b0393d10c 100644
--- a/packages/x-charts-pro/src/FunnelChart/FunnelPlot.tsx
+++ b/packages/x-charts-pro/src/FunnelChart/FunnelPlot.tsx
@@ -209,7 +209,7 @@ const useAggregatedData = () => {
});
});
- return result.flat();
+ return result;
}, [seriesData, xAxis, xAxisIds, yAxis, yAxisIds, gap]);
return allData;
@@ -222,36 +222,56 @@ function FunnelPlot(props: FunnelPlotProps) {
return (
- {data.map(({ d, color, id, seriesId, dataIndex, variant }) => (
- {
- onItemClick(event, { type: 'funnel', seriesId, dataIndex });
- })
- }
- />
- ))}
- {data.map(({ id, label, seriesId, dataIndex }) => {
- if (!label || !label.value) {
+ {data.map((series) => {
+ if (series.length === 0) {
return null;
}
return (
-
+
+ {series.map(({ d, color, id, seriesId, dataIndex, variant }) => (
+ {
+ onItemClick(event, { type: 'funnel', seriesId, dataIndex });
+ })
+ }
+ />
+ ))}
+
+ );
+ })}
+ {data.map((series) => {
+ if (series.length === 0) {
+ return null;
+ }
+
+ return (
+
+ {series.map(({ id, label, seriesId, dataIndex }) => {
+ if (!label || !label.value) {
+ return null;
+ }
+
+ return (
+
+ );
+ })}
+
);
})}
diff --git a/packages/x-charts-pro/src/FunnelChart/FunnelSection.tsx b/packages/x-charts-pro/src/FunnelChart/FunnelSection.tsx
index 30ae2d74464a0..31717ede51c92 100644
--- a/packages/x-charts-pro/src/FunnelChart/FunnelSection.tsx
+++ b/packages/x-charts-pro/src/FunnelChart/FunnelSection.tsx
@@ -62,6 +62,8 @@ const FunnelSection = consumeSlots(
strokeWidth={isOutlined ? 1.5 : 0}
cursor={onClick ? 'pointer' : 'unset'}
onClick={onClick}
+ data-highlighted={isHighlighted || undefined}
+ data-faded={isFaded || undefined}
className={clsx(
classes?.root,
isHighlighted && classes?.highlighted,