Skip to content

Commit 52330d2

Browse files
[charts] Clean the axis rendering (#8948)
1 parent d7ac79c commit 52330d2

File tree

11 files changed

+350
-163
lines changed

11 files changed

+350
-163
lines changed
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import {
2+
unstable_generateUtilityClass as generateUtilityClass,
3+
unstable_generateUtilityClasses as generateUtilityClasses,
4+
} from '@mui/utils';
5+
6+
export interface AxisClasses {
7+
/** Styles applied to the root element. */
8+
root: string;
9+
/** Styles applied to the main line element. */
10+
line: string;
11+
/** Styles applied to group ingruding the tick and its label. */
12+
tickContainer: string;
13+
/** Styles applied to ticks. */
14+
tick: string;
15+
/** Styles applied to ticks label. */
16+
tickLabel: string;
17+
/** Styles applied to the axis label. */
18+
label: string;
19+
/** Styles applied to x axes. */
20+
directionX: string;
21+
/** Styles applied to y axes. */
22+
directionY: string;
23+
/** Styles applied to the top axis. */
24+
top: string;
25+
/** Styles applied to the bottom axis. */
26+
bottom: string;
27+
/** Styles applied to the left axis. */
28+
left: string;
29+
/** Styles applied to the right axis. */
30+
right: string;
31+
}
32+
33+
export type XAxisClassKey = keyof AxisClasses;
34+
35+
export function getAxisUtilityClass(slot: string) {
36+
return generateUtilityClass('MuiAxis', slot);
37+
}
38+
39+
export const axisClasses: AxisClasses = generateUtilityClasses('MuiAxis', [
40+
'root',
41+
'line',
42+
'tickContainer',
43+
'tick',
44+
'tickLabel',
45+
'label',
46+
'directionX',
47+
'directionY',
48+
'top',
49+
'bottom',
50+
'left',
51+
'right',
52+
]);

packages/x-charts/src/BarChart/BarChart.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ export function BarChart(props: BarChartProps) {
5757
tooltip?.trigger !== 'axis' && highlight?.x === 'none' && highlight?.y === 'none'
5858
}
5959
>
60-
<BarPlot />
6160
<Axis topAxis={topAxis} leftAxis={leftAxis} rightAxis={rightAxis} bottomAxis={bottomAxis} />
61+
<BarPlot />
6262
<Highlight {...highlight} />
6363
<Tooltip {...tooltip} />
6464
{children}

packages/x-charts/src/LineChart/LineChart.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,8 @@ export function LineChart(props: LineChartProps) {
5656
tooltip?.trigger !== 'axis' && highlight?.x === 'none' && highlight?.y === 'none'
5757
}
5858
>
59-
<LinePlot />
6059
<Axis topAxis={topAxis} leftAxis={leftAxis} rightAxis={rightAxis} bottomAxis={bottomAxis} />
60+
<LinePlot />
6161

6262
<Highlight {...highlight} />
6363
<Tooltip {...tooltip} />

packages/x-charts/src/ScatterChart/ScatterChart.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ export function ScatterChart(props: ScatterChartProps) {
4343
yAxis={yAxis}
4444
sx={sx}
4545
>
46-
<ScatterPlot />
4746
<Axis topAxis={topAxis} leftAxis={leftAxis} rightAxis={rightAxis} bottomAxis={bottomAxis} />
47+
<ScatterPlot />
4848
<Highlight x="none" y="none" {...highlight} />
4949
<Tooltip trigger="item" {...tooltip} />
5050
{children}

packages/x-charts/src/XAxis/XAxis.tsx

Lines changed: 63 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,98 @@
11
import * as React from 'react';
2+
import { unstable_composeClasses as composeClasses } from '@mui/utils';
3+
import { useThemeProps, useTheme, Theme } from '@mui/material/styles';
24
import { CartesianContext } from '../context/CartesianContextProvider';
35
import { DrawingContext } from '../context/DrawingProvider';
46
import useTicks from '../hooks/useTicks';
57
import { XAxisProps } from '../models/axis';
8+
import { getAxisUtilityClass } from '../Axis/axisClasses';
9+
import { Line, Tick, TickLabel, Label } from '../internals/components/AxisSharedComponents';
610

7-
export function XAxis(props: XAxisProps) {
11+
const useUtilityClasses = (ownerState: XAxisProps & { theme: Theme }) => {
12+
const { classes, position } = ownerState;
13+
const slots = {
14+
root: ['root', 'directionX', position],
15+
line: ['line'],
16+
tickContainer: ['tickContainer'],
17+
tick: ['tick'],
18+
tickLabel: ['tickLabel'],
19+
label: ['label'],
20+
};
21+
22+
return composeClasses(slots, getAxisUtilityClass, classes);
23+
};
24+
const defaultProps = {
25+
position: 'bottom',
26+
disableLine: false,
27+
disableTicks: false,
28+
tickFontSize: 10,
29+
labelFontSize: 14,
30+
tickSize: 6,
31+
} as const;
32+
33+
export function XAxis(inProps: XAxisProps) {
34+
const props = useThemeProps({ props: { ...defaultProps, ...inProps }, name: 'MuiXAxis' });
835
const {
936
xAxis: {
10-
[props.axisId]: { scale: xScale, ...settings },
37+
[props.axisId]: { scale: xScale, ticksNumber, ...settings },
1138
},
1239
} = React.useContext(CartesianContext);
40+
41+
const defaultizedProps = { ...defaultProps, ...settings, ...props };
1342
const {
14-
position = 'bottom',
15-
disableLine = false,
16-
disableTicks = false,
17-
fill = 'currentColor',
18-
fontSize = 10,
43+
position,
44+
disableLine,
45+
disableTicks,
46+
tickFontSize,
1947
label,
20-
labelFontSize = 14,
21-
stroke = 'currentColor',
22-
tickSize: tickSizeProp = 6,
23-
} = { ...settings, ...props };
48+
labelFontSize,
49+
tickSize: tickSizeProp,
50+
} = defaultizedProps;
51+
52+
const theme = useTheme();
53+
const classes = useUtilityClasses({ ...defaultizedProps, theme });
2454

2555
const { left, top, width, height } = React.useContext(DrawingContext);
2656

2757
const tickSize = disableTicks ? 4 : tickSizeProp;
2858

29-
const xTicks = useTicks({ scale: xScale });
30-
59+
const xTicks = useTicks({ scale: xScale, ticksNumber });
3160
const positionSigne = position === 'bottom' ? 1 : -1;
3261

3362
return (
34-
<g transform={`translate(0, ${position === 'bottom' ? top + height : top})`}>
63+
<g
64+
transform={`translate(0, ${position === 'bottom' ? top + height : top})`}
65+
className={classes.root}
66+
>
3567
{!disableLine && (
36-
<line
37-
x1={xScale.range()[0]}
38-
x2={xScale.range()[1]}
39-
stroke={stroke}
40-
shapeRendering="crispEdges"
41-
/>
68+
<Line x1={xScale.range()[0]} x2={xScale.range()[1]} className={classes.line} />
4269
)}
4370
{xTicks.map(({ value, offset }, index) => (
44-
<g key={index} transform={`translate(${offset}, 0)`}>
45-
{!disableTicks && (
46-
<line y2={positionSigne * tickSize} stroke={stroke} shapeRendering="crispEdges" />
47-
)}
48-
<text
49-
fill={fill}
50-
transform={`translate(0, ${positionSigne * (fontSize + tickSize + 2)})`}
51-
textAnchor="middle"
52-
fontSize={fontSize}
71+
<g key={index} transform={`translate(${offset}, 0)`} className={classes.tickContainer}>
72+
{!disableTicks && <Tick y2={positionSigne * tickSize} className={classes.tick} />}
73+
<TickLabel
74+
transform={`translate(0, ${positionSigne * (tickFontSize + tickSize + 2)})`}
75+
sx={{
76+
fontSize: tickFontSize,
77+
}}
78+
className={classes.tickLabel}
5379
>
5480
{value.toLocaleString()}
55-
</text>
81+
</TickLabel>
5682
</g>
5783
))}
5884
{label && (
59-
<text
60-
fill={fill}
85+
<Label
6186
transform={`translate(${left + width / 2}, ${
62-
positionSigne * (fontSize + tickSize + 20)
87+
positionSigne * (tickFontSize + tickSize + 20)
6388
})`}
64-
fontSize={labelFontSize}
65-
textAnchor="middle"
89+
sx={{
90+
fontSize: labelFontSize,
91+
}}
92+
className={classes.label}
6693
>
6794
{label}
68-
</text>
95+
</Label>
6996
)}
7097
</g>
7198
);

packages/x-charts/src/YAxis/YAxis.tsx

Lines changed: 65 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,100 @@
11
import * as React from 'react';
2+
import { unstable_composeClasses as composeClasses } from '@mui/utils';
3+
import { useThemeProps, useTheme, Theme } from '@mui/material/styles';
24
import { CartesianContext } from '../context/CartesianContextProvider';
35
import { DrawingContext } from '../context/DrawingProvider';
46
import useTicks from '../hooks/useTicks';
57
import { YAxisProps } from '../models/axis';
8+
import { Line, Tick, TickLabel, Label } from '../internals/components/AxisSharedComponents';
9+
import { getAxisUtilityClass } from '../Axis/axisClasses';
610

7-
export function YAxis(props: YAxisProps) {
11+
const useUtilityClasses = (ownerState: YAxisProps & { theme: Theme }) => {
12+
const { classes, position } = ownerState;
13+
const slots = {
14+
root: ['root', 'directionY', position],
15+
line: ['line'],
16+
tickContainer: ['tickContainer'],
17+
tick: ['tick'],
18+
tickLabel: ['tickLabel'],
19+
label: ['label'],
20+
};
21+
22+
return composeClasses(slots, getAxisUtilityClass, classes);
23+
};
24+
25+
const defaultProps = {
26+
position: 'left',
27+
disableLine: false,
28+
disableTicks: false,
29+
tickFontSize: 10,
30+
labelFontSize: 14,
31+
tickSize: 6,
32+
} as const;
33+
34+
export function YAxis(inProps: YAxisProps) {
35+
const props = useThemeProps({ props: { ...defaultProps, ...inProps }, name: 'MuiYAxis' });
836
const {
937
yAxis: {
10-
[props.axisId]: { scale: yScale, ...settings },
38+
[props.axisId]: { scale: yScale, ticksNumber, ...settings },
1139
},
1240
} = React.useContext(CartesianContext);
41+
42+
const defaultizedProps = { ...defaultProps, ...settings, ...props };
1343
const {
14-
position = 'left',
15-
disableLine = false,
16-
disableTicks = false,
17-
fill = 'currentColor',
18-
fontSize = 10,
44+
position,
45+
disableLine,
46+
disableTicks,
47+
tickFontSize,
1948
label,
20-
labelFontSize = 14,
21-
stroke = 'currentColor',
22-
tickSize: tickSizeProp = 6,
23-
} = { ...settings, ...props };
49+
labelFontSize,
50+
tickSize: tickSizeProp,
51+
} = defaultizedProps;
52+
53+
const theme = useTheme();
54+
const classes = useUtilityClasses({ ...defaultizedProps, theme });
2455

2556
const { left, top, width, height } = React.useContext(DrawingContext);
2657

2758
const tickSize = disableTicks ? 4 : tickSizeProp;
2859

29-
const yTicks = useTicks({ scale: yScale });
60+
const yTicks = useTicks({ scale: yScale, ticksNumber });
3061

3162
const positionSigne = position === 'right' ? 1 : -1;
63+
3264
return (
33-
<g transform={`translate(${position === 'right' ? left + width : left}, 0)`}>
65+
<g
66+
transform={`translate(${position === 'right' ? left + width : left}, 0)`}
67+
className={classes.root}
68+
>
3469
{!disableLine && (
35-
<line
36-
y1={yScale.range()[0]}
37-
y2={yScale.range()[1]}
38-
stroke={stroke}
39-
shapeRendering="crispEdges"
40-
/>
70+
<Line y1={yScale.range()[0]} y2={yScale.range()[1]} className={classes.line} />
4171
)}
4272
{yTicks.map(({ value, offset }, index) => (
43-
<g key={index} transform={`translate(0, ${offset})`}>
44-
{!disableTicks && (
45-
<line x2={positionSigne * tickSize} stroke={stroke} shapeRendering="crispEdges" />
46-
)}
47-
<text
48-
fill={fill}
49-
transform={`translate(${positionSigne * (fontSize + tickSize + 2)}, 0)`}
50-
textAnchor="middle"
51-
fontSize={fontSize}
73+
<g key={index} transform={`translate(0, ${offset})`} className={classes.tickContainer}>
74+
{!disableTicks && <Tick x2={positionSigne * tickSize} className={classes.tick} />}
75+
<TickLabel
76+
transform={`translate(${positionSigne * (tickFontSize + tickSize + 2)}, 0)`}
77+
sx={{
78+
fontSize: tickFontSize,
79+
}}
80+
className={classes.tickLabel}
5281
>
5382
{value}
54-
</text>
83+
</TickLabel>
5584
</g>
5685
))}
5786
{label && (
58-
<text
59-
fill={fill}
60-
style={{}}
61-
transform={`translate(${positionSigne * (fontSize + tickSize + 20)}, ${
87+
<Label
88+
transform={`translate(${positionSigne * (tickFontSize + tickSize + 20)}, ${
6289
top + height / 2
6390
}) rotate(${positionSigne * 90})`}
64-
fontSize={labelFontSize}
65-
textAnchor="middle"
91+
sx={{
92+
fontSize: labelFontSize,
93+
}}
94+
className={classes.label}
6695
>
6796
{label}
68-
</text>
97+
</Label>
6998
)}
7099
</g>
71100
);

0 commit comments

Comments
 (0)