Skip to content

Commit 51a6dc5

Browse files
[docs] Add a demo for a custom tick label (#20073)
Signed-off-by: Prakhar Gupta <[email protected]> Signed-off-by: Bernardo Belchior <[email protected]> Co-authored-by: Bernardo Belchior <[email protected]> Co-authored-by: Bernardo Belchior <[email protected]>
1 parent fc6ab97 commit 51a6dc5

File tree

6 files changed

+175
-0
lines changed

6 files changed

+175
-0
lines changed
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import * as React from 'react';
2+
import Box from '@mui/material/Box';
3+
import { ChartContainer } from '@mui/x-charts/ChartContainer';
4+
import { BarPlot } from '@mui/x-charts/BarChart';
5+
import { ChartsXAxis } from '@mui/x-charts/ChartsXAxis';
6+
import { ChartsYAxis } from '@mui/x-charts/ChartsYAxis';
7+
8+
const iconMap = {
9+
Netflix: '/static/x/charts/netflix-logo.png',
10+
Alphabet: '/static/x/charts/google-logo.png',
11+
Microsoft: '/static/x/charts/microsoft-logo.png',
12+
};
13+
14+
function CustomTick(props) {
15+
const { x, y, text } = props;
16+
const logo = iconMap[text];
17+
18+
return (
19+
<g transform={`translate(${x},${y})`}>
20+
<foreignObject x={-20} y={-10} width={60} height={50}>
21+
<div
22+
style={{
23+
display: 'flex',
24+
justifyContent: 'center',
25+
alignItems: 'center',
26+
}}
27+
>
28+
<Box
29+
sx={{
30+
width: '100%',
31+
height: '100%',
32+
display: 'flex',
33+
flexDirection: 'column',
34+
alignItems: 'center',
35+
justifyContent: 'center',
36+
}}
37+
>
38+
{logo && (
39+
<img
40+
src={logo}
41+
alt={text}
42+
style={{
43+
width: '40px',
44+
height: '40px',
45+
objectFit: 'contain',
46+
}}
47+
/>
48+
)}
49+
</Box>
50+
</div>
51+
</foreignObject>
52+
</g>
53+
);
54+
}
55+
56+
export default function TickLabelSVG() {
57+
return (
58+
<Box sx={{ width: '100%', maxWidth: 600 }}>
59+
<ChartContainer
60+
xAxis={[
61+
{
62+
scaleType: 'band',
63+
data: ['Netflix', 'Alphabet', 'Microsoft'],
64+
id: 'companies',
65+
},
66+
]}
67+
yAxis={[{ id: 'revenue', position: 'left', width: 60 }]}
68+
series={[
69+
{
70+
type: 'bar',
71+
yAxisId: 'revenue',
72+
data: [39, 350, 245.1],
73+
},
74+
]}
75+
height={300}
76+
>
77+
<BarPlot />
78+
<ChartsXAxis axisId="companies" slots={{ axisTickLabel: CustomTick }} />
79+
<ChartsYAxis axisId="revenue" label="FY 2024 revenue in USD Billions" />
80+
</ChartContainer>
81+
</Box>
82+
);
83+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import * as React from 'react';
2+
import Box from '@mui/material/Box';
3+
import { ChartContainer } from '@mui/x-charts/ChartContainer';
4+
import { BarPlot } from '@mui/x-charts/BarChart';
5+
import { ChartsXAxis } from '@mui/x-charts/ChartsXAxis';
6+
import { ChartsYAxis } from '@mui/x-charts/ChartsYAxis';
7+
import { ChartsTextProps } from '@mui/x-charts/ChartsText';
8+
9+
const iconMap: Record<string, string> = {
10+
Netflix: '/static/x/charts/netflix-logo.png',
11+
Alphabet: '/static/x/charts/google-logo.png',
12+
Microsoft: '/static/x/charts/microsoft-logo.png',
13+
};
14+
15+
function CustomTick(props: ChartsTextProps) {
16+
const { x, y, text } = props;
17+
const logo = iconMap[text];
18+
19+
return (
20+
<g transform={`translate(${x},${y})`}>
21+
<foreignObject x={-20} y={-10} width={60} height={50}>
22+
<div
23+
style={{
24+
display: 'flex',
25+
justifyContent: 'center',
26+
alignItems: 'center',
27+
}}
28+
>
29+
<Box
30+
sx={{
31+
width: '100%',
32+
height: '100%',
33+
display: 'flex',
34+
flexDirection: 'column',
35+
alignItems: 'center',
36+
justifyContent: 'center',
37+
}}
38+
>
39+
{logo && (
40+
<img
41+
src={logo}
42+
alt={text}
43+
style={{
44+
width: '40px',
45+
height: '40px',
46+
objectFit: 'contain',
47+
}}
48+
/>
49+
)}
50+
</Box>
51+
</div>
52+
</foreignObject>
53+
</g>
54+
);
55+
}
56+
57+
export default function TickLabelSVG() {
58+
return (
59+
<Box sx={{ width: '100%', maxWidth: 600 }}>
60+
<ChartContainer
61+
xAxis={[
62+
{
63+
scaleType: 'band',
64+
data: ['Netflix', 'Alphabet', 'Microsoft'],
65+
id: 'companies',
66+
},
67+
]}
68+
yAxis={[{ id: 'revenue', position: 'left', width: 60 }]}
69+
series={[
70+
{
71+
type: 'bar',
72+
yAxisId: 'revenue',
73+
data: [39, 350, 245.1],
74+
},
75+
]}
76+
height={300}
77+
>
78+
<BarPlot />
79+
<ChartsXAxis axisId="companies" slots={{ axisTickLabel: CustomTick }} />
80+
<ChartsYAxis axisId="revenue" label="FY 2024 revenue in USD Billions" />
81+
</ChartContainer>
82+
</Box>
83+
);
84+
}

docs/data/charts/axis/axis.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,14 @@ You can test how these values behave and relate to one another in the demo below
270270

271271
{{"demo": "AxisTextCustomization.js", "hideToolbar": true, "bg": "playground"}}
272272

273+
### Adding tick label icons
274+
275+
A `foreignObject` element can be used to render non-SVG elements inside SVGs. You can leverage this to create components that interact with the charts data. In the demo below, custom tick labels are built by displaying an icon below the text.
276+
277+
Bear in mind that using `foreignObject` might prevent charts from being [exported](/x/react-charts/export/).
278+
279+
{{"demo": "TickLabelSVG.js"}}
280+
273281
## Symlog scale
274282

275283
A log scale cannot plot zero because log(0) is undefined.
18.6 KB
Loading
14.1 KB
Loading
13 KB
Loading

0 commit comments

Comments
 (0)