Skip to content

Conversation

@bernardobelchior
Copy link
Member

@bernardobelchior bernardobelchior commented Nov 11, 2025

Part of #12960.

Adds a tickSpacing property that defines the minimum space in pixels between ticks. At the moment, this is only used for ordinal scales. This should improve performance significantly while also improving the look of ticks in bar charts with many data points.

Ideally, in v9 we'd set this default to 50px, similar to continuous scales.

Demo

image

@bernardobelchior bernardobelchior added type: enhancement It’s an improvement, but we can’t make up our mind whether it's a bug fix or a new feature. scope: charts Changes related to the charts. labels Nov 11, 2025
@mui-bot
Copy link

mui-bot commented Nov 11, 2025

Deploy preview: https://deploy-preview-20282--material-ui-x.netlify.app/

Updated pages:

Bundle size report

Bundle Parsed size Gzip size
@mui/x-data-grid 0B(0.00%) 0B(0.00%)
@mui/x-data-grid-pro 0B(0.00%) 0B(0.00%)
@mui/x-data-grid-premium 0B(0.00%) 0B(0.00%)
@mui/x-charts 🔺+287B(+0.08%) 🔺+127B(+0.12%)
@mui/x-charts-pro 🔺+286B(+0.06%) 🔺+106B(+0.08%)
@mui/x-charts-premium 🔺+287B(+0.06%) 🔺+123B(+0.09%)
@mui/x-date-pickers 0B(0.00%) 0B(0.00%)
@mui/x-date-pickers-pro 0B(0.00%) 0B(0.00%)
@mui/x-tree-view 0B(0.00%) 0B(0.00%)
@mui/x-tree-view-pro 0B(0.00%) 0B(0.00%)

Details of bundle changes

Generated by 🚫 dangerJS against 9d34f31

*/
tickLabelPlacement?: 'middle' | 'tick';
/**
* The space between ticks when using an ordinal scale. It defines the minimum distance in pixels between two ticks.
Copy link
Member Author

Choose a reason for hiding this comment

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

Should we only apply this to ordinal scales?

tickLabelPlacement?: 'middle' | 'tick';
/**
* The space between ticks when using an ordinal scale. It defines the minimum distance in pixels between two ticks.
* @default 0
Copy link
Member Author

@bernardobelchior bernardobelchior Nov 11, 2025

Choose a reason for hiding this comment

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

Do we want to increase the default in v9? Linear scales indirectly use 50 for this (because it calculates the default tick number as range[1] - range[0] / 50)

Copy link
Member

Choose a reason for hiding this comment

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

Do we need a default value? For me we could have no default value.

For me the ordinal ticks should display all ticks by default. It feels more natural to modify a configuration to sub sample ticks than having to modify the config to see all your ticks

I'm thinking about bar charts like those

image

Copy link
Member

Choose a reason for hiding this comment

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

Yeah I wouldn't increase it either

Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
* @default 0

*/
tickLabelPlacement?: 'middle' | 'tick';
/**
* The space between ticks when using an ordinal scale. It defines the minimum distance in pixels between two ticks.
Copy link
Member Author

Choose a reason for hiding this comment

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

Need to document how this interacts/conflicts with tickMinStep, tickMaxStep, tickLabelInterval and tickLabelMinGap

Copy link
Member

Choose a reason for hiding this comment

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

Need to document how this interacts/conflicts with tickMinStep, tickMaxStep, tickLabelInterval and tickLabelMinGap

For now it does not interact, because those are for continuous scale only (except for tickInterval)

What about

The minimum distance in pixels between two ticks.

  • For ordinal scale, ticks are filtered out to match the distance.
  • For continuous scale, the tickSpacing is used to compute the tickumber if not defined.

Copy link
Member Author

Choose a reason for hiding this comment

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

For continuous scale, the tickSpacing is used to compute the tickumber if not defined.

For continuous scales we're defaulting this to 50, so it would only work if we change the default depending on the scale type.

@bernardobelchior
Copy link
Member Author

bernardobelchior commented Nov 11, 2025

Using a tick spacing of 50 in the example below allowed me to reduce the rendering time by 400ms (from 1.15s to 750ms, 4x CPU throttling).

image

With this plus a batch scatter plot, I think we can reduce a large bar chart's rendering time significantly.

@bernardobelchior
Copy link
Member Author

@alexfauquette your input would be especially appreciated here as you've worked on a similar topic 😄

@github-actions github-actions bot added the PR: out-of-date The pull request has merge conflicts and can't be merged. label Nov 21, 2025
@github-actions
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 Nov 24, 2025
@codspeed-hq
Copy link

codspeed-hq bot commented Nov 24, 2025

CodSpeed Performance Report

Merging #20282 will not alter performance

Comparing bernardobelchior:band-tick-spacing (9d34f31) with master (7160d7b)1

Summary

✅ 13 untouched

Footnotes

  1. No successful run was found on master (dd38206) during the generation of this report, so 7160d7b was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

@bernardobelchior bernardobelchior force-pushed the band-tick-spacing branch 2 times, most recently from 5336655 to 7824e1b Compare November 26, 2025 11:28
@bernardobelchior bernardobelchior marked this pull request as ready for review November 26, 2025 15:52
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.

The behavior looks good, and it's a nice move in direction of more resposive charts.

Sorry for the delay in reviewing this PR

Comment on lines 92 to 99
const every = Math.ceil(domain.length / (rangeSpan / tickSpacing));
return domain.filter((_, index) => index % every === 0);
}
Copy link
Member

@alexfauquette alexfauquette Nov 27, 2025

Choose a reason for hiding this comment

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

To handle the case tick spacing = 0

Suggested change
const every = Math.ceil(domain.length / (rangeSpan / tickSpacing));
return domain.filter((_, index) => index % every === 0);
}
const every = Math.ceil(domain.length * tickSpacing / rangeSpan);
if(Number.isNaN(every) || every <= 1){
return domain;
}
return domain.filter((_, index) => index % every === 0);
}

Copy link
Member Author

Choose a reason for hiding this comment

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

I stated that assumption in the documentation of the function:

Assumes tick spacing is greater than 0.

Do we need to handle it? It should already be ensured by the caller.

Copy link
Member

Choose a reason for hiding this comment

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

It cost nothing, plus add an extra savings:

  • avoid to run filter if the every is equal to 1
  • do no crash rangeSpan is 0

*/
tickLabelPlacement?: 'middle' | 'tick';
/**
* The space between ticks when using an ordinal scale. It defines the minimum distance in pixels between two ticks.
Copy link
Member

Choose a reason for hiding this comment

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

Need to document how this interacts/conflicts with tickMinStep, tickMaxStep, tickLabelInterval and tickLabelMinGap

For now it does not interact, because those are for continuous scale only (except for tickInterval)

What about

The minimum distance in pixels between two ticks.

  • For ordinal scale, ticks are filtered out to match the distance.
  • For continuous scale, the tickSpacing is used to compute the tickumber if not defined.

tickLabelPlacement?: 'middle' | 'tick';
/**
* The space between ticks when using an ordinal scale. It defines the minimum distance in pixels between two ticks.
* @default 0
Copy link
Member

Choose a reason for hiding this comment

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

Do we need a default value? For me we could have no default value.

For me the ordinal ticks should display all ticks by default. It feels more natural to modify a configuration to sub sample ticks than having to modify the config to see all your ticks

I'm thinking about bar charts like those

image

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.

Mostly minor comments to polish

tickLabelPlacement?: 'middle' | 'tick';
/**
* The space between ticks when using an ordinal scale. It defines the minimum distance in pixels between two ticks.
* @default 0
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
* @default 0

filteredDomain = filteredDomain.filter(tickInterval);
}

if (tickSpacing !== undefined && tickSpacing > 0) {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
if (tickSpacing !== undefined && tickSpacing > 0) {
if (tickSpacing) {

Copy link
Member Author

Choose a reason for hiding this comment

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

I find the current way of writing more explicit, otherwise it might not be clear that this isn't an oversight. I can replace it with a comment if you prefer, though

tickLabelInterval?: 'auto' | ((value: any, index: number) => boolean);
/**
* The minimum space between ticks when using an ordinal scale. It defines the minimum distance in pixels between two ticks.
* @default 0
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
* @default 0

Copy link
Member Author

Choose a reason for hiding this comment

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

Why should we remove the default?

Copy link
Member

Choose a reason for hiding this comment

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

Why adding a default instead of just considering that if not provided it has no effect?

Plus it will stay accurate if at some point we extend the impact of this property to continuous axes

Copy link
Member Author

Choose a reason for hiding this comment

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

just considering that if not provided it has no effect

Should we state that instead, then? Otherwise I don't think it's clear for users what the default value is.

If they're looking at this prop for the first time, isn't it plausible that we set a default value different than 0?

Comment on lines 152 to 158
You can use the `tickSpacing` property to define the minimum spacing in pixels between two ticks in ordinal scales.

By default, this value is set to 0, so there is no minimum spacing between ticks.

For band scales where hidden ticks can be interpolated, such as numbers and dates, the tick spacing can be set to a positive value.

This should improve the readability of the axis by reducing the number of ticks shown as well as improve performance when there is a large number of ticks.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
You can use the `tickSpacing` property to define the minimum spacing in pixels between two ticks in ordinal scales.
By default, this value is set to 0, so there is no minimum spacing between ticks.
For band scales where hidden ticks can be interpolated, such as numbers and dates, the tick spacing can be set to a positive value.
This should improve the readability of the axis by reducing the number of ticks shown as well as improve performance when there is a large number of ticks.
Use the `tickSpacing` property to define the minimum spacing in pixels between two ticks.
Having a minimal space between ticks improves the readability and the performances of the axis.
This property is only available for ordinal axes (the one with band and point scale).

Copy link
Member Author

Choose a reason for hiding this comment

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

I've rewritten some of this paragraph, but why do you think we should remove the usage suggestion and the default value? I think it's useful info

Copy link
Member

Choose a reason for hiding this comment

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

I think documentation readers have a small capacity for attention.

  • The explanation on the default is a full sentence to explain what happen if they don't set this property. But they already have their code running, or they have seen dozens of bar chart before so they intuitively know there is a tick per category by default
  • About the usage, I've not removed it. I only focused on what I think matters the most:
    • It's interesting for readability and performances 👍
    • The fact that values should be interoperable: That's a concern for us, not for the users. They have a particular dataset to display, so they intuitively know if they can remove ticks or not.
    • insist on the fact it only works on ordinal scales, to be sure people don't lose their mind trying to make this work on a continuous one

Copy link
Member Author

Choose a reason for hiding this comment

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

Makes sense. I tried shortening the docs even further

@bernardobelchior bernardobelchior merged commit a37ad24 into mui:master Dec 3, 2025
22 checks passed
@bernardobelchior bernardobelchior deleted the band-tick-spacing branch December 3, 2025 10:50
A-s-h-o-k pushed a commit to A-s-h-o-k/mui-x that referenced this pull request Dec 14, 2025
mapache-salvaje pushed a commit to mapache-salvaje/mui-x that referenced this pull request Dec 29, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

scope: charts Changes related to the charts. type: enhancement It’s an improvement, but we can’t make up our mind whether it's a bug fix or a new feature.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants