Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[charts] Allows to customize elements color based on its value #11277

Closed
RayHughes opened this issue Dec 2, 2023 · 10 comments · Fixed by #12490
Closed

[charts] Allows to customize elements color based on its value #11277

RayHughes opened this issue Dec 2, 2023 · 10 comments · Fixed by #12490
Assignees
Labels
component: charts This is the name of the generic UI component, not the React module! enhancement This is not a bug, nor a new feature

Comments

@RayHughes
Copy link

RayHughes commented Dec 2, 2023

The problem in depth 🔍

I am trying to make the chart below with X Charts:

Screenshot 2023-12-02 at 1 10 12 AM

The bars in the chart should be color coordinated based on wether or not they exceed the horizontal position of ChartsReferenceLine, with green being above and red being below.

I was able to build the structure pretty easily using ResponsiveChartContainer. How should I go about calculating the color if I do not have access to the position of ChartsReferenceLine?

The value of the bar is not available in the prop passed thru to the slots props on the bar, so I would need to compare the position of the reference line to that of the height of the bar.

I tried using a series for this but because series groups its not practical. Only the first color of colors is on ResponsiveChartContainer is respected for BarCharts

Attempts

Basic Structure
https://codesandbox.io/p/sandbox/mui-bar-chart-with-rounded-corders-right-forked-s5yd28?file=%2FDemo.js

With Slot (and BarElement export workaround)

https://codesandbox.io/p/sandbox/mui-bar-chart-with-rounded-corders-right-forked-q73qzp?file=%2FDemo.js%3A22%2C30

Your environment 🌎

System:
OS: macOS 14.1.1
Binaries:
Node: 20.5.1 - /opt/homebrew/bin/node
Yarn: 1.22.21 - ~/Desktop/Projects/web/node_modules/.bin/yarn
npm: 9.8.0 - /opt/homebrew/bin/npm
Browsers:
Chrome: 119.0.6045.199
Edge: Not Found
Safari: 17.1
npmPackages:
@emotion/react: ^11.10.6 => 11.10.6
@emotion/styled: ^11.10.6 => 11.10.6
@mui/base: 5.0.0-alpha.126
@mui/core-downloads-tracker: 5.12.1
@mui/lab: ^5.0.0-alpha.127 => 5.0.0-alpha.127
@mui/material: ^5.12.1 => 5.12.1
@mui/private-theming: 5.12.0
@mui/styled-engine: 5.12.0
@mui/system: 5.12.1
@mui/types: 7.2.4
@mui/utils: 5.12.0
@mui/x-charts: ^v7.0.0-alpha.2 => 7.0.0-alpha.2
@mui/x-data-grid: 6.18.2
@mui/x-data-grid-pro: ^6.18.2 => 6.18.2
@mui/x-license-pro: 6.10.2
@types/react: ^18.0.26 => 18.0.26
react: ^18.2.0 => 18.2.0
react-dom: ^18.2.0 => 18.2.0
typescript: ^5.1.6 => 5.1.6

  Don't forget to mention which browser you used.
  Output from `npx @mui/envinfo` goes here.

Search keywords: bar chart color customization
Order ID: 58383

@RayHughes RayHughes added status: waiting for maintainer These issues haven't been looked at yet by a maintainer support: commercial Support request from paid users labels Dec 2, 2023
@RayHughes
Copy link
Author

RayHughes commented Dec 2, 2023

I solved this using the useYScale hook. Not sure if it's the best solution. Feedback appreciated.

A side affect is that the hover element has the wrong bar color associated

Once the BarElement export fix is released the custom rect can be replaced. #11234

Updated Code Pen: https://codesandbox.io/p/sandbox/mui-bar-chart-with-rounded-corders-right-forked-trvfp4?file=%2FDemo.js

export const BarChart = () => {
  const SlotBarElement = (props) =>{
    const yAxisScale = useYScale('left_axis_id')
    const yAxisValue = yAxisScale.invert(props.style.y.animation.to)
    const isBelowBar = yAxisValue < 8.5
    const color = isBelowBar ? '#ff0000' : '#00ff00'

    // work around export of BarElement
    return <rect
      fill={color}
      height={props.style.height.animation.to}
      width={props.style.width.animation.to}
      x={props.style.x.animation.to}
      y={props.style.y.animation.to}
    />
  }

  return (
    <ResponsiveChartContainer
        height={350}
        series={[
          { type: 'bar', data: [11, 10, 1, 9], yAxisKey: 'left_axis_id'},
        ]}
        xAxis={[{ scaleType: 'band', data: ['11/15', '11/16', '11/17', '11/18'] }]}
        yAxis={[{ id: 'left_axis_id'}]}
    >
      <BarPlot slots={{bar: SlotBarElement}}/>
      <ChartsXAxis />
      <ChartsYAxis axisId="left_axis_id" position="left"/>
      <ChartsReferenceLine label={'8.5'} labelAlign="end" y={8.5}/>
      <ChartsTooltip/>
    </ResponsiveChartContainer>
  )
}

@RayHughes RayHughes changed the title [question] How to individually style bar chart colors? [question] How do I change the color of a bar in a bar chart when it's below a threshold? Dec 2, 2023
@RayHughes
Copy link
Author

For some reason the colors do not change automatically. Sometimes I have to mouse over the chart before they swap. Any thoughts why?

@oliviertassinari oliviertassinari added the component: charts This is the name of the generic UI component, not the React module! label Dec 5, 2023
@alexfauquette
Copy link
Member

About why you need to pass the mouse over, the props.style.y.animation.to is NaN at first render so your component does not render.

About how to get the information, using the useScale sounds to be ok. Maybe better would be that we pass this information to the component to simplify this.

For now, the ownerState get id and dataIndex which are the series' id and the index of the data rendered. So if you data is not too complicated, the best might be to rely on that information.

https://codesandbox.io/p/sandbox/mui-bar-chart-with-rounded-corders-right-forked-h5jvsd?file=%2FDemo.js%3A17%2C52-17%2C54

@RayHughes
Copy link
Author

Thank you @alexfauquette this resolved my problem!!

@alexfauquette
Copy link
Member

I'm just keeping this issue open to track the progress on simplifying conditional rendering of bar elements

@alexfauquette alexfauquette reopened this Dec 5, 2023
@alexfauquette alexfauquette removed the status: waiting for maintainer These issues haven't been looked at yet by a maintainer label Dec 5, 2023
@alexfauquette alexfauquette changed the title [question] How do I change the color of a bar in a bar chart when it's below a threshold? [charts] Allows to customize elements color based on its value Dec 5, 2023
@alexfauquette alexfauquette added enhancement This is not a bug, nor a new feature and removed support: commercial Support request from paid users labels Dec 5, 2023
@RayHughes
Copy link
Author

I'm just keeping this issue open to track the progress on simplifying conditional rendering of bar elements

Makes sense..

I noticed the tooltip popup shows the default bar color and not the custom color of the bar. It's not a big deal for me, but figured I'd call it out since you're using this for tracking.

@alexfauquette
Copy link
Member

I noticed the tooltip popup shows the default bar color and not the custom color of the bar.

Interesting. That's a sign the customization should probably not be into the component customization (bar, line, ...) but at a higher level to have coherence between chart element, the legend and the tooltip

@alexfauquette
Copy link
Member

For grouping same topic issues, here is the suggestion of similar behavior for the grid

Have you considered the option/need to have conditional grid color styling?
Wouldn't it be problem adding it in given the current API?

#11034 (review)

@alexfauquette
Copy link
Member

@RayHughes You might be interested by #12490 and the preview demonstration visible in https://deploy-preview-12490--material-ui-x.netlify.app/x/react-charts/bars/#color-scale

The over all idea is to map values to color in the different axes. Any feedback about the developer experience is welcome :)

Copy link

⚠️ This issue has been closed. If you have a similar problem but not exactly the same, please open a new issue.
Now, if you have additional information related to this issue or things that could help future readers, feel free to leave a comment.

@RayHughes: How did we do? Your experience with our support team matters to us. If you have a moment, please share your thoughts in this short Support Satisfaction survey.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component: charts This is the name of the generic UI component, not the React module! enhancement This is not a bug, nor a new feature
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants