-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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] Introduce the radar chart #16406
base: master
Are you sure you want to change the base?
Conversation
Deploy preview: https://deploy-preview-16406--material-ui-x.netlify.app/ Updated pages: |
37ed9fc
to
a95fddc
Compare
This pull request has conflicts, please resolve those before we can evaluate the pull request. |
a589b3a
to
e1b7842
Compare
CodSpeed Performance ReportMerging #16406 will not alter performanceComparing Summary
|
This pull request has conflicts, please resolve those before we can evaluate the pull request. |
|
||
The radar chart displays a grid behind the series that can be configured with | ||
|
||
- `startAngle` The rotation angle of the entire chart |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it make sense to mention the angle should be specified in degrees?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think it should be startAngleDeg
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I should have been more specific. I was suggesting something along the lines of:
- `startAngle` The rotation angle of the entire chart in degrees
The radar chart displays a grid behind the series that can be configured with | ||
|
||
- `startAngle` The rotation angle of the entire chart | ||
- `divisionNumber` The nb of division of the grid |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if it would make more sense to write "number" here. It might not be clear "nb" means number.
degreeToRad((axis as RotationConfig).endAngle, 2 * Math.PI), | ||
]; | ||
const diff = angles[1] - angles[0]; | ||
if (diff > Math.PI * 2 - 0.1) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe I'm missing some context here. What is the reason for subtracting specifically by 0.1?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To take into account the risk of computation errors that could lead to diff === 2*Math.PI
being false for less that 0.1
We could move that to 0.001. But I assume polar axes are either displayed on 360° in which case we need to avoid the overlap of first and last point. Or 180° in which case we have nothing to do
params: UseChartPolarAxisParameters; | ||
defaultizedParams: UseChartPolarAxisDefaultizedParameters; | ||
state: UseChartPolarAxisState; | ||
// instance: UseChartPolarAxisInstance; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just double-checking: is this commented on purpose?
valueType: DefaultizedPieValueType; | ||
}; | ||
radar: { | ||
seriesInput: DefaultizedProps<RadarSeriesType, 'id'> & { color: string }; | ||
series: DefaultizedRadarSeriesType; | ||
seriesProp: RadarSeriesType; | ||
itemIdentifier: RadarItemIdentifier; | ||
valueType: number; | ||
polar: true; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just curious: why do we need a polar: true
prop here, but not for the pie chart?
As I see it, the pie chart is also polar where the radius is constant and only the rotation axis changes, isn't it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume it is because pie chart doesn't really use polar coordinates, since it can be much simpler.
I assume this got carried over because of how we handle the This would make the styles more consistent, but might create other issues 🫠 |
The `metrics` property of `radar` takes an array with one item per corner of the radar. | ||
This item can either be: | ||
|
||
- A string used as the axis label. The other properties will be defaulted. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- A string used as the axis label. The other properties will be defaulted. | |
- A string used as the axis label. The other properties are populated from the data. |
I feel that defaulted
usually has a negative connotation, we should probably not use it in documents. Eg: "John defaulted on his loans"
Another option is to fully remove the second phrase as well, it doesn't add much information.
// @ts-ignore | ||
onAxisClick, | ||
disableAxisListener, | ||
// @ts-ignore | ||
highlightedItem, | ||
// @ts-ignore | ||
onHighlightChange, | ||
sx, | ||
title, | ||
// @ts-ignore | ||
xAxis, | ||
// @ts-ignore | ||
yAxis, | ||
// @ts-ignore | ||
zAxis, | ||
// @ts-ignore | ||
rotationAxis, | ||
// @ts-ignore | ||
radiusAxis, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Eh, these are bad 😅
Might as well have "any" as type.
WDYT about moving these type changes to a different PR so we can discuss them in isolation? 🤔
// The effect do not track any value defined synchronously during the 1st render by hooks called after `useChartPolarAxis` | ||
// As a consequence, the state generated by the 1st run of this useEffect will always be equal to the initialization one |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't understand this comment
testSkipIf(!isJSDOM)('should throw an error when axis have duplicate ids', () => { | ||
const expectedError = [ | ||
'MUI X: The following axis ids are duplicated: qwerty.', | ||
'Please make sure that each axis has a unique id.', | ||
].join('\n'); | ||
|
||
expect(() => | ||
render( | ||
<BarChart | ||
xAxis={[ | ||
{ scaleType: 'band', id: 'qwerty', data: ['a', 'b', 'c'] }, | ||
{ scaleType: 'band', id: 'qwerty', data: ['a', 'b', 'c'] }, | ||
]} | ||
series={[{ data: [1, 2, 3] }]} | ||
height={100} | ||
width={100} | ||
/>, | ||
), | ||
).toErrorDev(expectedError); | ||
}); | ||
|
||
// can't catch render errors in the browser for unknown reason | ||
// tried try-catch + error boundary + window onError preventDefault | ||
testSkipIf(!isJSDOM)( | ||
'should throw an error when axis have duplicate ids across different directions (x,y)', | ||
() => { | ||
const expectedError = [ | ||
'MUI X: The following axis ids are duplicated: qwerty.', | ||
'Please make sure that each axis has a unique id.', | ||
].join('\n'); | ||
|
||
expect(() => | ||
render( | ||
<BarChart | ||
xAxis={[{ scaleType: 'band', id: 'qwerty', data: ['a', 'b', 'c'] }]} | ||
yAxis={[{ id: 'qwerty' }]} | ||
series={[{ data: [1, 2, 3] }]} | ||
height={100} | ||
width={100} | ||
/>, | ||
), | ||
).toErrorDev(expectedError); | ||
}, | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess you missed the tests here 😆
export interface RadarDataProviderProps | ||
extends Omit< | ||
ChartContainerProps<'radar', RadarPluginSignatures>, | ||
'series' | 'plugins' | 'rotationAxis' | 'radiusAxis' | 'dataset' | ||
> { | ||
/** | ||
* The series to display in the bar chart. | ||
* An array of [[RadarSeriesType]] objects. | ||
*/ | ||
series: MakeOptional<RadarSeriesType, 'type'>[]; | ||
/** | ||
* The configuration of the radar scales. | ||
*/ | ||
radar: RadarConfig; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the API, sounds reasonable. series
handles the series, radar
is the chart config 👍
Hm, good points. I don't have any suggestions at the moment, but I'll let you know if I can think of something. |
This pull request has conflicts, please resolve those before we can evaluate the pull request. |
This PR is a rough first version of the Radar chart #7925. Lots of features are missing.
The idea is to validate the data structure, and it's mapping to a rotation/radius scale system. If ok, we can merge this one and add features in distinct PR such that we keep them small enough to be relevant (I don't expect someone to read 200 files with 10 different features and spot any bug or room for improvement)
Main idea
The polar plugin introduce the support of rotatio/radius axes that work similarly to the x/y axes
The radar don't expose directly those axies. It uses an intermediate
metrics
to make sure the radar has only one rotation axis with scale point, and one radius axis per metric.Then we have one component per item rendered (grid, area, and marks)
Features
Preview: https://deploy-preview-16406--material-ui-x.netlify.app/x/react-charts/radar/