-
-
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] Render axis title within axis size #16730
[charts] Render axis title within axis size #16730
Conversation
Deploy preview: https://deploy-preview-16730--material-ui-x.netlify.app/ Updated pages: |
CodSpeed Performance ReportMerging #16730 will not alter performanceComparing Summary
|
This pull request has conflicts, please resolve those before we can evaluate the pull request. |
41164c9
to
ad6067b
Compare
@JCQuintas @alexfauquette here a point I'd like your opinion on: Increase default y-axis widthFrom the demos that I've updated in this PR, setting I'd suggest updating that default to 60px. We can discuss whether to increase the Here's why: the default label has a font size of 14px and the default tick size is 6px wide. This means that the remaining space must fit the tick label plus some spacing to look good. With our default configuration, the tick labels "100" and "1,000" are 21.5px and 31.5px wide respectively. The default axis label has a font size of 14px and the default tick size is 6px. This means that we need at least 41.5px to render an axis label, a tick label with the text "100" and the default tick size. When displaying "1,000", we'll need 51.5px, and this isn't taking into account any spacing we might want to have to ensure an appealing look. As such, I'd suggest a default of 60px, since I feel like looks good for 1-character labels and 3-character labels. For numbers over 999, it might be still acceptable, but for more digits the axis width would need to be increased. I propose that we split this increase by setting the default axis width to 40 and the default label width to 20. Here's how it would look like if we reduced the margin to 16px: Here's an example with 12px: We'd need to then update some demos, such as this one (margin = 12px): What do you think? Is it fine to update the axis width? What about the margin? |
I've reduced line-height to 1, which should move the axis labels closer to the edge. From looking at the Do you know where I can find that last example so I can test it as well? |
I've just updated the demo at with the default values http://localhost:3001/x/react-charts/styling/#placement |
@@ -118,6 +120,7 @@ const defaultProps = { | |||
disableTicks: false, | |||
tickSize: 6, | |||
tickLabelMinGap: 4, | |||
height: DEFAULT_AXIS_SIZE_HEIGHT, |
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.
This doesn't seem necessary, the height gets initialised elsewhere
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.
Yeah, there seems to be a TypeScript issue because if I remove this I'll get an error.
Our types are a bit complex, so I'm having a hard time understanding how to fix this, but basically there's no place where we're defining that height
is actually not undefined.
Do you have any suggestion on how to fix this?
We can do something like this:
export type AxisDefaultized<
S extends ScaleName = ScaleName,
V = any,
AxisProps extends ChartsAxisProps = ChartsXAxisProps | ChartsYAxisProps,
> = MakeRequired<Omit<AxisConfig<S, V, AxisProps>, 'scaleType'>, 'offset'> &
AxisScaleConfig[S] &
AxisSideConfig<AxisProps> &
AxisScaleComputedConfig[S] & {
/**
* An indication of the expected number of ticks.
*/
tickNumber: number;
} & AxisProps extends ChartsXAxisProps
? { height: number }
: AxisProps extends ChartsYAxisProps
? { width: number }
: never;
However, I'm thinking if it makes sense to separate AxisDefaultized
into XAxisDefaultized
and YAxisDefaultized
. We already have ZAxisDefaultized
and it would simplify types by not needing to use extends
in some places.
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.
However, I'm thinking if it makes sense to separate
AxisDefaultized
intoXAxisDefaultized
andYAxisDefaultized
. We already haveZAxisDefaultized
and it would simplify types by not needing to useextends
in some places.
I thought the same previously, so probably we should try it at least.
You can also probably just mark the entire AxisSideConfig
as Required
Required<AxisSideConfig<AxisProps>>
export type AxisDefaultized<
S extends ScaleName = ScaleName,
V = any,
AxisProps extends ChartsAxisProps = ChartsXAxisProps | ChartsYAxisProps,
> = MakeRequired<Omit<AxisConfig<S, V, AxisProps>, 'scaleType'>, 'offset'> &
AxisScaleConfig[S] &
Required<AxisSideConfig<AxisProps>> &
AxisScaleComputedConfig[S] & {
/**
* An indication of the expected number of ticks.
*/
tickNumber: number;
};
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 don't think I can do Required<AxisSideConfig<AxisProps>>
because position
can be undefined
for axes that aren't the first (source), but I'll do something similar.
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.
MakeOptional<Required<AxisSideConfig<AxisProps>>, 'position'>
🤣
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.
Apparently it breaks types in computeAxisValue
🤔
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.
Also, we might want to add the position
from line 48 into the sharedConfig
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 why I didn't do that, might have side effects
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.
Yeah, there seem to be an error in our TypeScript types.
It seems defaultizeAxis
is called before computeAxisValue
, but here in computeAxisValue
we're stating that the type is AxisConfig
instead of AxisDefaultized
. This is problematic because I'm getting an error because height
/width
aren't defined, but they are. It's just that the types are wrong.
I can fix this by adding height: 0
before spreading axis
, but it seems to me that our store has incorrect types.
@alexfauquette @JCQuintas are you aware of this? Is there any reason for it?
const height = | ||
axisName === 'x' | ||
? DEFAULT_AXIS_SIZE_HEIGHT + (axisConfig.label ? AXIS_LABEL_DEFAULT_HEIGHT : 0) | ||
: 0; | ||
const width = | ||
axisName === 'y' | ||
? DEFAULT_AXIS_SIZE_WIDTH + (axisConfig.label ? AXIS_LABEL_DEFAULT_HEIGHT : 0) | ||
: 0; |
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.
This makes me think if we should instead of having a fixed height/width. We define it based on the axis extremums? 🤔 We would probably need to move the computation elsewhere, to the cartesianaxis plugin probably.
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.
From what I see the decision is between:
- The axis size is fixed, and labels get elpises or wrapped to fit in
- The axis size get updated according to its content
The first one seems easier to do and customize than the second 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.
Yes, but the second one would be better for the user.
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.
Yes, but the second one would be better for the user.
It does not look that obvious. The two behaviors have advantages and issues, depending on the context (how much control you have on the data, labels, and sizing)
Since we are in beta phase, I would be in favor of doing as few last breaking changes on axes as possible. We might go with:
- Fix axis sizes with a best effort default (taking into consideration the presence or not of the axis title)
- Move the axis title position from fixed point to the end of the axis sizes
- Have tick labels cut if they overflow a given dimension
From that point, we would have a significant improvement, and could continue working toward point 2 as an optional configuration.
It would not be breaking changes, because enabling this feature will require to pass some options
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 agree that a height: 'auto'
or width: 'auto'
would be useful, but then we get into other problems (e.g., how much of a chart should a label take up? What happens if a label is larger than the total chart width?).
I agree with Alex that we should keep changes incremental, but I'd also like to eventually have fully responsive axes (potentially with a minSize
/maxSize
prop). When I was searching for a charting library in the past, this was something that I felt was missing from many libraries and that I ended up having to implement myself, so I think there's value in providing this by default.
4b44a7c
to
936112e
Compare
34cfc91
to
7a9cb8b
Compare
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.
The logic seems good. I just left comment about duplicated places where theme
and lineHeight
are propagated. Othe than that it's good for me.
I added a changelog in the description. I should probably be added to the migration guide
* measurements to be off. As such, it is recommended to apply those properties through the `labelStyle` prop. */ | ||
...theme.typography.body1, | ||
lineHeight: 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.
* measurements to be off. As such, it is recommended to apply those properties through the `labelStyle` prop. */ | |
...theme.typography.body1, | |
lineHeight: 1, | |
* measurements to be off. As such, it is recommended to apply those properties through the `labelStyle` prop. */ |
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.
See #16730 (comment)
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.
The idea of this proposal is to remove the theme.typography.body1
and lineHeight
from axis labels since they are already specified in the default style
of ChartXAxis
and ChartYAxis
.
Here you're adding styling to .Mui-ChartAxis-root .Mui-ChartAxis-label
but the component will get a styled
props that override them with the same value
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.
Sure, I think that works 👍
a41de1c
to
316e6b7
Compare
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 just wait for the relesae before merging 😇
… default values for Y axes.
33d2701
to
72656c3
Compare
Render axis title within axis size. Precursor to #16709.
At the moment we hardcode the render position of the axis title regardless of its size or axis height.
The problem of this approach is that increasing the axis height does not change the position of the axis title. This makes it hard to solve issues with overflowing labels that are rotated, since the only way to change the axis title position is to apply a
translateY()
transformation.With this PR, we'll position the axis title at the outer edge of the axis container, i.e., bottom edge for an axis with
position: 'bottom'
, left edge for an axis withposition: 'left'
.This provides the maximum space for tick labels to be shown.
Changelog
The axis label default position is now set to the outermost bound of the axis size (introduced in v8).
Instead of increasing the chart margin, and translating the label, you can now increase the axis size to get a similar result.
A consequence of this change is that the specificity of some styles changed, so make sure you check your axis label position and appearance after upgrading.