How to put rounded corners on a MUI X charts Bar chart?

1.5k views Asked by At

I have created a chart using MUI X barchart,

import { BarChart } from '@mui/x-charts/BarChart';
import { ThemeProvider, createTheme, useTheme } from '@mui/material/styles';

and I want to give the bars rounded corners. I tried borderRadius for sx property and series property. but it didn't work. the sx property creates a border around the chart not for every bar. I have the following code so far:

 <ThemeProvider theme={darkTheme}  >
    <BarChart
       
        sx={[{p: 5, border: 1, borderRadius: 3}]}
        yAxis={[
              {
               id: 'barCategories',
               data: ['A', 'B', 'C', 'D', 'E'],
               scaleType: 'band',
              },
         ]}
         series={[
                {
                 data: [50, 20, 85, 60, 20],
                 color: '#fff',
                },
                            
          ]}
          layout="horizontal"
     />
</ThemeProvider>

and it looks like this: enter image description here

How can I make the bars looks rounded corners like this:

enter image description here

2

There are 2 answers

2
Steve G On BEST ANSWER

Because the underlying bar element for MUI Bar Chart is an SVG rect element, you will not be able to apply CSS border-radius. But you can provide your own custom Bar component that, instead of rendering a rect element, renders a path element appearing as a rectangle with rounded corners1 and pass that component via the slots prop.

For example:

<BarChart
  ...
  layout="horizontal"
  slots={{
    bar: (props) => {
      const radius = 7;
      const {x, y, height, width, ownerState, ...restProps} = props
      
      // Path of a rectangle with rounded corners on the right
      // for horizontal layout
      const d = `M${x},${y} h${width - radius} a${radius},${radius} 0 0 1 ${radius},${radius}v ${height - 2 * radius} a${radius},${radius} 0 0 1 ${-radius},${radius} h${radius - width}z`
      return <path d={d} fill={ownerState.color}
      {...restProps} />
    }
  }}
    />

Which produces:

example bar chart with rounded corners

(I would memo this for better performance -- this demo is just to get you rolling.)

Working CodeSanbox: https://codesandbox.io/s/mui-bar-chart-with-rounded-corders-right-zms2m5?file=/Demo.js

1 You could also create a component that still uses a rect and provide a clipPath for the rounded corners, but IMO this is the simpler option.

References:

1
Muhammad Anas On

Steve's response didnt work correctly for me so what I did is passed the same Slot prop into the Barchart Component.

I was not getting the response thorugh destructring so I had to convert it to string and then parse it again. (it is not a good practise, But if it is necessary make a commons folder and define the logic separately and pass it here as a function)

`<barChart
//Your other props

    slots={{
              bar: (props) => {
                const { style } = props;
                const str = JSON.stringify(style);
                const arr = JSON.parse(str);
                const { x, y, height, width } = arr;
    
                let radius = width;
            
                const d = `M${x},${y} h${width - radius} a${radius},${radius} 0 0 1 ${radius},${radius}v ${height - 2 * radius} a${radius},${radius} 0 0 1 ${-radius},${radius} h${radius - width}z`
                return <path d={d}></path>;
              },
            }}
           />`