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] Decouple margin and axis-size #16418

Merged
merged 75 commits into from
Feb 20, 2025
Merged

Conversation

JCQuintas
Copy link
Member

@JCQuintas JCQuintas commented Jan 31, 2025

Fixes #16387
Fixes #16383

Changelog

Breaking change

  • Replace topAxis, rightAxis, bottomAxis, and leftAxis props by position in the axis config

    The following props have been removed from the axis config: topAxis, rightAxis, bottomAxis, and leftAxis.

    Replaced the topAxis, rightAxis, bottomAxis and leftAxis props by a position prop in the axis config that accepts 'top' | 'right' | 'bottom' | 'left' | 'none'.

    If you were previously disabling an axis by setting it to null, you should now set its position to 'none'.

     <LineChart
       yAxis={[
         {
           scaleType: 'linear',
    +      position: 'right',
         },
       ]}
       series={[{ data: [1, 10, 30, 50, 70, 90, 100], label: 'linear' }]}
       height={400}
    -  rightAxis={{}}
     />
  • Remove position prop from ChartsXAxis and ChartsYAxis

    The position prop has been removed from the ChartsXAxis and ChartsYAxis components. Configure it directly in the axis config.

     <ChartContainer
       yAxis={[
         {
           id: 'my-axis',
    +      position: 'right',
         },
       ]}
     >
    -  <ChartsYAxis axisId="my-axis" position="right" />
    +  <ChartsYAxis axisId="my-axis" />
     </ChartContainer>

@JCQuintas JCQuintas added breaking change enhancement This is not a bug, nor a new feature component: charts This is the name of the generic UI component, not the React module! labels Jan 31, 2025
@JCQuintas JCQuintas self-assigned this Jan 31, 2025
Copy link

codspeed-hq bot commented Jan 31, 2025

CodSpeed Performance Report

Merging #16418 will not alter performance

Comparing JCQuintas:axis-size-poc (acbc0eb) with master (15f5a84)

Summary

✅ 6 untouched benchmarks

@JCQuintas
Copy link
Member Author

JCQuintas commented Feb 3, 2025

@alexfauquette having the config in either the plugin or in the component cause a re-render which slows up the chart.

An alternative could be to get rid of left/right/top/bottomAxis properties, move all the config into the x/yAxis, which will then process everything before they render as far as I'm aware. 🤔

eg:

<LineChart
  xAxis={[
    {
      data: ['A', 'B', 'C', 'D'],
      scaleType: 'point',
      position: 'right',
    },
  ]}
  series={[{ data: [40, 30, 20, 10] }]}
  height={200}
/>

@alexfauquette
Copy link
Member

alexfauquette commented Feb 3, 2025

An alternative could be to get rid of left/right/top/bottomAxis properties, move all the config into the x/yAxis, which will then process everything before they render as far as I'm aware. 🤔

Sounds reasonable. Wwe will need to find a hack to let the selectorChartDrawingArea accept to support this new notion of axis dimensions depending on the existence of the cartesian axis plugging or not.

You would still have the plugin in the following order "dimensions > series > axes" but the dimensions could have a selector that uses xAxis and yAxis config if available. The selectorChartDrawingArea would depend on two selectors selectorChartMargin and selectorChartAxisSpace.

If later we want to adapt the size according the real space an axis takes we will also need to take into account the zoom and the tick we render.

I assume the idea is then to have something like

xAxis={[
    {
      data: ['A', 'B', 'C', 'D'],
      scaleType: 'point',
      position: 'right',
      width: 95 // specify the space taken by the axis.
    },
  ]}

@alexfauquette
Copy link
Member

By the way, the removal of leftAxis, ... can be done in a non breaking way.

We can deprecate the props and keep default the same

@JCQuintas
Copy link
Member Author

@mui/xcharts what do you think about this API? I still have to make height/width count towards the margins, but it was trivial to allow multiple axis on a side in this implementation 😄

Screenshot 2025-02-05 at 17 58 34
import * as React from 'react';
import { BarChart } from '@mui/x-charts/BarChart';

export default function BasicBars() {
  return (
    <BarChart
      xAxis={[
        { scaleType: 'band', data: ['group A', 'group B', 'group C'], position: 'top' },
        { scaleType: 'band', data: ['group 1', 'group 2', 'group 3'], position: 'top' }
      ]}
      series={[{ data: [4, 3, 5] }, { data: [1, 6, 3] }, { data: [2, 5, 6] }]}
      margin={60}
      width={500}
      height={300}
    />
  );
}

@alexfauquette
Copy link
Member

I was effectively thinking of this issue #16387 about multiple axis as a nice example of what this new axis config could fix :)

I'm good with the API, and adding width and height as properties that get defaulted on x/y axes.
I would be against something like { position: 'top', size: { width: 50, height: 150 } } because for x-axis user will only care about the height, and with y-axis only about width.

Copy link

github-actions bot commented Feb 7, 2025

This pull request has conflicts, please resolve those before we can evaluate the pull request.

@github-actions github-actions bot added the PR: out-of-date The pull request has merge conflicts and can't be merged label Feb 7, 2025
@github-actions github-actions bot removed the PR: out-of-date The pull request has merge conflicts and can't be merged label Feb 7, 2025
@github-actions github-actions bot removed the PR: out-of-date The pull request has merge conflicts and can't be merged label Feb 18, 2025
Copy link

This pull request has conflicts, please resolve those before we can evaluate the pull request.

@github-actions github-actions bot added PR: out-of-date The pull request has merge conflicts and can't be merged and removed PR: out-of-date The pull request has merge conflicts and can't be merged labels Feb 18, 2025
@@ -201,12 +191,14 @@ const SparkLineChart = React.forwardRef(function SparkLineChart(
data: Array.from({ length: data.length }, (_, index) => index),
hideTooltip: xAxis === undefined,
...xAxis,
position: 'none',
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mui/xcharts one possible disadvantage of the current approach is that the axis is being counted for sizing purposes even if ChartsAxis is not present in the document.

Since we have "defaults", I guess it would be difficult to prevent this kind of behavior :/

@alexfauquette
Copy link
Member

You have an error in one of the screen shots (the axis/HidingAxis.tsx) All the other looks good

image

About the sparkling, it's not an issue for me. It's part of the tradeoff we discussed. If someone does not render the axes (like us in the sparkling) or do a custom rendering. They should update the position and sizing of the axis.

Comment on lines 290 to 292
The following props have been removed from the axis config: `topAxis`, `rightAxis`, `bottomAxis`, and `leftAxis`.

Replaced the `topAxis`, `rightAxis`, `bottomAxis` and `leftAxis` props by a `position` prop in the axis config that accepts `'top' | 'right' | 'bottom' | 'left' | 'none'`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks a bit duplicated with the title. Maybe something more like

The following props have been removed topAxis, rightAxis, bottomAxis, and leftAxis.
To modify the axis placement, use the new position property in the axis config.
It accepts 'top' | 'right' | 'bottom' | 'left' | 'none'.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe also at the end a small sentence to highlight why doing that:

Notice this new API allows you to [stack multiple axes on the same side of the chart](link to the demo)

@github-actions github-actions bot added the PR: out-of-date The pull request has merge conflicts and can't be merged label Feb 19, 2025
Copy link

This pull request has conflicts, please resolve those before we can evaluate the pull request.

@github-actions github-actions bot removed the PR: out-of-date The pull request has merge conflicts and can't be merged label Feb 19, 2025
Copy link
Member

@alexfauquette alexfauquette left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀

Copy link
Member

@bernardobelchior bernardobelchior left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left a comment, not a blocker, but probably something we want to tackle post-merge.

Comment on lines 241 to 243
* It's used for leaving some space for extra information such as the x- and y-axis or legend.
* Accepts an object with the optional properties: `top`, `bottom`, `left`, and `right`.
*/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this up to date? The axes are no longer part of the margin, are they?

Also, we now also accept a single number, right?

@JCQuintas JCQuintas merged commit 68412f1 into mui:master Feb 20, 2025
19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
breaking change 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
4 participants