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] Clean the axis rendering #8948

Merged
merged 10 commits into from
May 16, 2023
52 changes: 52 additions & 0 deletions packages/x-charts/src/Axis/axisClasses.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import {
unstable_generateUtilityClass as generateUtilityClass,
unstable_generateUtilityClasses as generateUtilityClasses,
} from '@mui/utils';

export interface AxisClasses {
/** Styles applied to the root element. */
root: string;
/** Styles applied to the main line element. */
line: string;
/** Styles applied to group ingruding the tick and its label. */
tickContainer: string;
/** Styles applied to ticks. */
tick: string;
/** Styles applied to ticks label. */
tickLabel: string;
/** Styles applied to the axis label. */
label: string;
/** Styles applied to x axes. */
directionX: string;
/** Styles applied to y axes. */
directionY: string;
/** Styles applied to the top axis. */
top: string;
/** Styles applied to the bottom axis. */
bottom: string;
/** Styles applied to the left axis. */
left: string;
/** Styles applied to the right axis. */
right: string;
}

export type XAxisClassKey = keyof AxisClasses;

export function getAxisUtilityClass(slot: string) {
return generateUtilityClass('MuiAxis', slot);
}

export const axisClasses: AxisClasses = generateUtilityClasses('MuiAxis', [
'root',
'line',
'tickContainer',
'tick',
'tickLabel',
'label',
'directionX',
'directionY',
'top',
'bottom',
'left',
'right',
]);
2 changes: 1 addition & 1 deletion packages/x-charts/src/BarChart/BarChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ export function BarChart(props: BarChartProps) {
tooltip?.trigger !== 'axis' && highlight?.x === 'none' && highlight?.y === 'none'
}
>
<BarPlot />
<Axis topAxis={topAxis} leftAxis={leftAxis} rightAxis={rightAxis} bottomAxis={bottomAxis} />
<BarPlot />
flaviendelangle marked this conversation as resolved.
Show resolved Hide resolved
<Highlight {...highlight} />
<Tooltip {...tooltip} />
{children}
Expand Down
2 changes: 1 addition & 1 deletion packages/x-charts/src/LineChart/LineChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ export function LineChart(props: LineChartProps) {
tooltip?.trigger !== 'axis' && highlight?.x === 'none' && highlight?.y === 'none'
}
>
<LinePlot />
<Axis topAxis={topAxis} leftAxis={leftAxis} rightAxis={rightAxis} bottomAxis={bottomAxis} />
<LinePlot />

<Highlight {...highlight} />
<Tooltip {...tooltip} />
Expand Down
2 changes: 1 addition & 1 deletion packages/x-charts/src/ScatterChart/ScatterChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ export function ScatterChart(props: ScatterChartProps) {
yAxis={yAxis}
sx={sx}
>
<ScatterPlot />
<Axis topAxis={topAxis} leftAxis={leftAxis} rightAxis={rightAxis} bottomAxis={bottomAxis} />
<ScatterPlot />
<Highlight x="none" y="none" {...highlight} />
<Tooltip trigger="item" {...tooltip} />
{children}
Expand Down
99 changes: 63 additions & 36 deletions packages/x-charts/src/XAxis/XAxis.tsx
Original file line number Diff line number Diff line change
@@ -1,71 +1,98 @@
import * as React from 'react';
import { unstable_composeClasses as composeClasses } from '@mui/utils';
import { useThemeProps, useTheme, Theme } from '@mui/material/styles';
import { CartesianContext } from '../context/CartesianContextProvider';
import { DrawingContext } from '../context/DrawingProvider';
import useTicks from '../hooks/useTicks';
import { XAxisProps } from '../models/axis';
import { getAxisUtilityClass } from '../Axis/axisClasses';
import { Line, Tick, TickLabel, Label } from '../internals/components/AxisSharedComponents';

export function XAxis(props: XAxisProps) {
const useUtilityClasses = (ownerState: XAxisProps & { theme: Theme }) => {
const { classes, position } = ownerState;
const slots = {
root: ['root', 'directionX', position],
line: ['line'],
tickContainer: ['tickContainer'],
tick: ['tick'],
tickLabel: ['tickLabel'],
label: ['label'],
};

return composeClasses(slots, getAxisUtilityClass, classes);
};
const defaultProps = {
position: 'bottom',
disableLine: false,
disableTicks: false,
tickFontSize: 10,
labelFontSize: 14,
tickSize: 6,
} as const;

export function XAxis(inProps: XAxisProps) {
const props = useThemeProps({ props: { ...defaultProps, ...inProps }, name: 'MuiXAxis' });
const {
xAxis: {
[props.axisId]: { scale: xScale, ...settings },
[props.axisId]: { scale: xScale, ticksNumber, ...settings },
},
} = React.useContext(CartesianContext);

const defaultizedProps = { ...defaultProps, ...settings, ...props };
const {
position = 'bottom',
disableLine = false,
disableTicks = false,
fill = 'currentColor',
fontSize = 10,
position,
disableLine,
disableTicks,
tickFontSize,
label,
labelFontSize = 14,
stroke = 'currentColor',
tickSize: tickSizeProp = 6,
} = { ...settings, ...props };
labelFontSize,
tickSize: tickSizeProp,
} = defaultizedProps;

const theme = useTheme();
const classes = useUtilityClasses({ ...defaultizedProps, theme });

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

const tickSize = disableTicks ? 4 : tickSizeProp;

const xTicks = useTicks({ scale: xScale });

const xTicks = useTicks({ scale: xScale, ticksNumber });
const positionSigne = position === 'bottom' ? 1 : -1;

return (
<g transform={`translate(0, ${position === 'bottom' ? top + height : top})`}>
<g
transform={`translate(0, ${position === 'bottom' ? top + height : top})`}
className={classes.root}
>
{!disableLine && (
<line
x1={xScale.range()[0]}
x2={xScale.range()[1]}
stroke={stroke}
shapeRendering="crispEdges"
/>
<Line x1={xScale.range()[0]} x2={xScale.range()[1]} className={classes.line} />
)}
{xTicks.map(({ value, offset }, index) => (
<g key={index} transform={`translate(${offset}, 0)`}>
{!disableTicks && (
<line y2={positionSigne * tickSize} stroke={stroke} shapeRendering="crispEdges" />
)}
<text
fill={fill}
transform={`translate(0, ${positionSigne * (fontSize + tickSize + 2)})`}
textAnchor="middle"
fontSize={fontSize}
<g key={index} transform={`translate(${offset}, 0)`} className={classes.tickContainer}>
{!disableTicks && <Tick y2={positionSigne * tickSize} className={classes.tick} />}
<TickLabel
transform={`translate(0, ${positionSigne * (tickFontSize + tickSize + 2)})`}
sx={{
fontSize: tickFontSize,
}}
className={classes.tickLabel}
>
{value.toLocaleString()}
</text>
</TickLabel>
</g>
))}
{label && (
<text
fill={fill}
<Label
transform={`translate(${left + width / 2}, ${
positionSigne * (fontSize + tickSize + 20)
positionSigne * (tickFontSize + tickSize + 20)
})`}
fontSize={labelFontSize}
textAnchor="middle"
sx={{
fontSize: labelFontSize,
}}
className={classes.label}
>
{label}
</text>
</Label>
)}
</g>
);
Expand Down
101 changes: 65 additions & 36 deletions packages/x-charts/src/YAxis/YAxis.tsx
Original file line number Diff line number Diff line change
@@ -1,71 +1,100 @@
import * as React from 'react';
import { unstable_composeClasses as composeClasses } from '@mui/utils';
import { useThemeProps, useTheme, Theme } from '@mui/material/styles';
import { CartesianContext } from '../context/CartesianContextProvider';
import { DrawingContext } from '../context/DrawingProvider';
import useTicks from '../hooks/useTicks';
import { YAxisProps } from '../models/axis';
import { Line, Tick, TickLabel, Label } from '../internals/components/AxisSharedComponents';
import { getAxisUtilityClass } from '../Axis/axisClasses';

export function YAxis(props: YAxisProps) {
const useUtilityClasses = (ownerState: YAxisProps & { theme: Theme }) => {
const { classes, position } = ownerState;
const slots = {
root: ['root', 'directionY', position],
line: ['line'],
tickContainer: ['tickContainer'],
tick: ['tick'],
tickLabel: ['tickLabel'],
label: ['label'],
};

return composeClasses(slots, getAxisUtilityClass, classes);
};

const defaultProps = {
position: 'left',
disableLine: false,
disableTicks: false,
tickFontSize: 10,
labelFontSize: 14,
tickSize: 6,
} as const;

export function YAxis(inProps: YAxisProps) {
const props = useThemeProps({ props: { ...defaultProps, ...inProps }, name: 'MuiYAxis' });
const {
yAxis: {
[props.axisId]: { scale: yScale, ...settings },
[props.axisId]: { scale: yScale, ticksNumber, ...settings },
},
} = React.useContext(CartesianContext);

const defaultizedProps = { ...defaultProps, ...settings, ...props };
const {
position = 'left',
disableLine = false,
disableTicks = false,
fill = 'currentColor',
fontSize = 10,
position,
disableLine,
disableTicks,
tickFontSize,
label,
labelFontSize = 14,
stroke = 'currentColor',
tickSize: tickSizeProp = 6,
} = { ...settings, ...props };
labelFontSize,
tickSize: tickSizeProp,
} = defaultizedProps;

const theme = useTheme();
const classes = useUtilityClasses({ ...defaultizedProps, theme });

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

const tickSize = disableTicks ? 4 : tickSizeProp;

const yTicks = useTicks({ scale: yScale });
const yTicks = useTicks({ scale: yScale, ticksNumber });

const positionSigne = position === 'right' ? 1 : -1;

return (
<g transform={`translate(${position === 'right' ? left + width : left}, 0)`}>
<g
transform={`translate(${position === 'right' ? left + width : left}, 0)`}
className={classes.root}
>
{!disableLine && (
<line
y1={yScale.range()[0]}
y2={yScale.range()[1]}
stroke={stroke}
shapeRendering="crispEdges"
/>
<Line y1={yScale.range()[0]} y2={yScale.range()[1]} className={classes.line} />
)}
{yTicks.map(({ value, offset }, index) => (
<g key={index} transform={`translate(0, ${offset})`}>
{!disableTicks && (
<line x2={positionSigne * tickSize} stroke={stroke} shapeRendering="crispEdges" />
)}
<text
fill={fill}
transform={`translate(${positionSigne * (fontSize + tickSize + 2)}, 0)`}
textAnchor="middle"
fontSize={fontSize}
<g key={index} transform={`translate(0, ${offset})`} className={classes.tickContainer}>
{!disableTicks && <Tick x2={positionSigne * tickSize} className={classes.tick} />}
<TickLabel
transform={`translate(${positionSigne * (tickFontSize + tickSize + 2)}, 0)`}
sx={{
fontSize: tickFontSize,
}}
className={classes.tickLabel}
>
{value}
</text>
</TickLabel>
</g>
))}
{label && (
<text
fill={fill}
style={{}}
transform={`translate(${positionSigne * (fontSize + tickSize + 20)}, ${
<Label
transform={`translate(${positionSigne * (tickFontSize + tickSize + 20)}, ${
top + height / 2
}) rotate(${positionSigne * 90})`}
fontSize={labelFontSize}
textAnchor="middle"
sx={{
fontSize: labelFontSize,
}}
className={classes.label}
>
{label}
</text>
</Label>
)}
</g>
);
Expand Down