diff --git a/docs/data/charts/styling/GradientTooltip.js b/docs/data/charts/styling/GradientTooltip.js new file mode 100644 index 0000000000000..37eabc894b977 --- /dev/null +++ b/docs/data/charts/styling/GradientTooltip.js @@ -0,0 +1,37 @@ +import * as React from 'react'; +import { BarChart } from '@mui/x-charts/BarChart'; + +export default function GradientTooltip() { + return ( + <BarChart + sx={{ + '--my-custom-gradient': 'url(#GlobalGradient)', + }} + slotProps={{ + popper: { + sx: { + '--my-custom-gradient': 'linear-gradient(0deg, #123456, #81b2e4);', + }, + }, + }} + series={[ + { + label: 'series A', + data: [50], + }, + { + label: 'series B', + data: [100], + color: 'var(--my-custom-gradient, #123456)', + }, + ]} + width={400} + height={200} + > + <linearGradient id="GlobalGradient" x1="0%" y1="100%" x2="0%" y2="0%"> + <stop offset="0" stopColor="#123456" /> + <stop offset="1" stopColor="#81b2e4" /> + </linearGradient> + </BarChart> + ); +} diff --git a/docs/data/charts/styling/GradientTooltip.tsx b/docs/data/charts/styling/GradientTooltip.tsx new file mode 100644 index 0000000000000..37eabc894b977 --- /dev/null +++ b/docs/data/charts/styling/GradientTooltip.tsx @@ -0,0 +1,37 @@ +import * as React from 'react'; +import { BarChart } from '@mui/x-charts/BarChart'; + +export default function GradientTooltip() { + return ( + <BarChart + sx={{ + '--my-custom-gradient': 'url(#GlobalGradient)', + }} + slotProps={{ + popper: { + sx: { + '--my-custom-gradient': 'linear-gradient(0deg, #123456, #81b2e4);', + }, + }, + }} + series={[ + { + label: 'series A', + data: [50], + }, + { + label: 'series B', + data: [100], + color: 'var(--my-custom-gradient, #123456)', + }, + ]} + width={400} + height={200} + > + <linearGradient id="GlobalGradient" x1="0%" y1="100%" x2="0%" y2="0%"> + <stop offset="0" stopColor="#123456" /> + <stop offset="1" stopColor="#81b2e4" /> + </linearGradient> + </BarChart> + ); +} diff --git a/docs/data/charts/styling/PatternPie.js b/docs/data/charts/styling/PatternPie.js new file mode 100644 index 0000000000000..02f53eebf0161 --- /dev/null +++ b/docs/data/charts/styling/PatternPie.js @@ -0,0 +1,44 @@ +import * as React from 'react'; +import { PieChart } from '@mui/x-charts/PieChart'; + +export default function PatternPie() { + return ( + <PieChart + sx={{ + '--my-custom-pattern': 'url(#Pattern)', + }} + series={[ + { + data: [ + { id: 0, value: 10, label: 'series A' }, + { id: 1, value: 15, label: 'series B' }, + { + id: 2, + value: 20, + label: 'series C', + color: 'var(--my-custom-pattern, #123456)', + }, + ], + }, + ]} + width={400} + height={200} + > + <pattern + id="Pattern" + patternUnits="userSpaceOnUse" + width="20" + height="40" + patternTransform="scale(0.5)" + > + <rect x="0" y="0" width="100%" height="100%" fill="#123456" /> + <path + d="M0 30h20L10 50zm-10-20h20L0 30zm20 0h20L20 30zM0-10h20L10 10z" + strokeWidth="1" + stroke="#81b2e4" + fill="none" + /> + </pattern> + </PieChart> + ); +} diff --git a/docs/data/charts/styling/PatternPie.tsx b/docs/data/charts/styling/PatternPie.tsx new file mode 100644 index 0000000000000..02f53eebf0161 --- /dev/null +++ b/docs/data/charts/styling/PatternPie.tsx @@ -0,0 +1,44 @@ +import * as React from 'react'; +import { PieChart } from '@mui/x-charts/PieChart'; + +export default function PatternPie() { + return ( + <PieChart + sx={{ + '--my-custom-pattern': 'url(#Pattern)', + }} + series={[ + { + data: [ + { id: 0, value: 10, label: 'series A' }, + { id: 1, value: 15, label: 'series B' }, + { + id: 2, + value: 20, + label: 'series C', + color: 'var(--my-custom-pattern, #123456)', + }, + ], + }, + ]} + width={400} + height={200} + > + <pattern + id="Pattern" + patternUnits="userSpaceOnUse" + width="20" + height="40" + patternTransform="scale(0.5)" + > + <rect x="0" y="0" width="100%" height="100%" fill="#123456" /> + <path + d="M0 30h20L10 50zm-10-20h20L0 30zm20 0h20L20 30zM0-10h20L10 10z" + strokeWidth="1" + stroke="#81b2e4" + fill="none" + /> + </pattern> + </PieChart> + ); +} diff --git a/docs/data/charts/styling/styling.md b/docs/data/charts/styling/styling.md index 9f795806ee5d0..fc64c9cb923d9 100644 --- a/docs/data/charts/styling/styling.md +++ b/docs/data/charts/styling/styling.md @@ -164,3 +164,22 @@ Chart components accept the `sx` props. From here, you can target any subcomponents with its class name. {{"demo": "SxStyling.js"}} + +### Gradients and patterns + +It is possible to use gradients and patterns to fill the charts. +This can be done by passing your gradient or pattern definition as children of the chart component. + +Note that the gradient or pattern defined that way is only usable for SVG. +So a direct definition like `color: "url(#Pattern)'` would cause undefined colors in HTML elements such as the tooltip. +The demo solves this issue by using a CSS variable `'--my-custom-pattern': 'url(#Pattern)'` to specify fallback color with `color: 'var(--my-custom-pattern, #123456)'`. + +{{"demo": "PatternPie.js"}} + +#### Using gradients on tooltips + +Gradients defined as SVG elements are not directly supported in HTML. +However you can use the [gradient functions](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Functions#gradient_functions) to define a gradient in CSS. +This gradient can be used in the tooltip by setting the `sx` prop on the tooltip component, instead of the fallback color used in the previous examples. + +{{"demo": "GradientTooltip.js"}} diff --git a/packages/x-charts/src/ChartsTooltip/ChartsTooltipTable.ts b/packages/x-charts/src/ChartsTooltip/ChartsTooltipTable.ts index a50e1c462c51c..e1334f6675cd1 100644 --- a/packages/x-charts/src/ChartsTooltip/ChartsTooltipTable.ts +++ b/packages/x-charts/src/ChartsTooltip/ChartsTooltipTable.ts @@ -85,7 +85,7 @@ export const ChartsTooltipMark = styled('div', { height: theme.spacing(1), borderRadius: '50%', boxShadow: theme.shadows[1], - backgroundColor: color, + background: color, borderColor: (theme.vars || theme).palette.background.paper, border: `solid ${(theme.vars || theme).palette.background.paper} ${theme.spacing(0.25)}`, boxSizing: 'content-box', diff --git a/packages/x-charts/src/PieChart/PieArc.tsx b/packages/x-charts/src/PieChart/PieArc.tsx index 6919b17363ed7..6f6c61104d629 100644 --- a/packages/x-charts/src/PieChart/PieArc.tsx +++ b/packages/x-charts/src/PieChart/PieArc.tsx @@ -42,9 +42,15 @@ export const pieArcClasses: PieArcClasses = generateUtilityClasses('MuiPieArc', ]); const useUtilityClasses = (ownerState: PieArcOwnerState) => { - const { classes, id, isFaded, isHighlighted } = ownerState; + const { classes, id, isFaded, isHighlighted, dataIndex } = ownerState; const slots = { - root: ['root', `series-${id}`, isHighlighted && 'highlighted', isFaded && 'faded'], + root: [ + 'root', + `series-${id}`, + `data-index-${dataIndex}`, + isHighlighted && 'highlighted', + isFaded && 'faded', + ], }; return composeClasses(slots, getPieArcUtilityClass, classes); @@ -55,9 +61,9 @@ const PieArcRoot = styled(animated.path, { slot: 'Root', overridesResolver: (_, styles) => styles.arc, })<{ ownerState: PieArcOwnerState }>(({ theme }) => ({ + // Got to move stroke to an element prop instead of style. stroke: (theme.vars || theme).palette.background.paper, - strokeWidth: 1, - strokeLinejoin: 'round', + transition: 'opacity 0.2s ease-in, fill 0.2s ease-in, filter 0.2s ease-in', })); export type PieArcProps = Omit<React.SVGProps<SVGPathElement>, 'ref' | 'id'> & @@ -124,6 +130,11 @@ function PieArc(props: PieArcProps) { cursor={onClick ? 'pointer' : 'unset'} ownerState={ownerState} className={classes.root} + fill={ownerState.color} + opacity={ownerState.isFaded ? 0.3 : 1} + filter={ownerState.isHighlighted ? 'brightness(120%)' : 'none'} + strokeWidth={1} + strokeLinejoin="round" {...other} {...getInteractionItemProps({ type: 'pie', seriesId: id, dataIndex })} /> diff --git a/packages/x-charts/src/PieChart/PieArcPlot.tsx b/packages/x-charts/src/PieChart/PieArcPlot.tsx index 13e233d5b642a..1a340402c5658 100644 --- a/packages/x-charts/src/PieChart/PieArcPlot.tsx +++ b/packages/x-charts/src/PieChart/PieArcPlot.tsx @@ -112,10 +112,8 @@ function PieArcPlot(props: PieArcPlotProps) { endAngle, paddingAngle: pA, innerRadius: iR, - arcLabelRadius, outerRadius: oR, cornerRadius: cR, - ...style }, item, _, @@ -129,7 +127,6 @@ function PieArcPlot(props: PieArcPlotProps) { innerRadius={iR} outerRadius={oR} cornerRadius={cR} - style={style} id={id} color={item.color} dataIndex={index}