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,