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] Allow onItemClick on the Legend component #14231

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
78824d6
Fix typo
JCQuintas Aug 16, 2024
3c40275
Add new class for item background
JCQuintas Aug 16, 2024
6b17d82
Implement on click legend
JCQuintas Aug 16, 2024
f46c598
fix types
JCQuintas Aug 16, 2024
1f4ce27
Rename to onItemClick
JCQuintas Aug 16, 2024
4120889
Rename type
JCQuintas Aug 21, 2024
2d99c87
OnItemClick to OnClick
JCQuintas Aug 21, 2024
f43eb68
Provide useful context on legend click
JCQuintas Aug 21, 2024
45504ab
Simplify logic
JCQuintas Aug 21, 2024
ab493cc
Improve typing
JCQuintas Aug 21, 2024
8f9d2aa
Add interactive docs
JCQuintas Aug 21, 2024
724461b
Merge branch 'master' into 12344-charts-legend-actions-eg-highlighting
JCQuintas Aug 27, 2024
016139e
Merge commit '6d78f4f039f3c65469ed3089e44f9dbdc491806d' into 12344-ch…
JCQuintas Aug 29, 2024
ef76263
Allow onItemClick on the base of the legend
JCQuintas Aug 29, 2024
07d4be0
Align typings and expose styling props
JCQuintas Aug 29, 2024
c159515
run scripts
JCQuintas Aug 29, 2024
acc7843
remove spilled typings
JCQuintas Aug 29, 2024
5050e79
Merge commit '3d767ba2d135e22956f15615ba7085a1ec3ef043' into 12344-ch…
JCQuintas Aug 29, 2024
9e669e5
Fix doc generation
JCQuintas Aug 29, 2024
98bd450
Fix order
JCQuintas Aug 29, 2024
73197d5
Remove need to pass context builder
JCQuintas Aug 29, 2024
ef88eca
Merge commit '2cb93f48795b650025c65c43d359c9373130068f' into 12344-ch…
JCQuintas Sep 2, 2024
2f87937
Remove hidden from piecewise
JCQuintas Sep 2, 2024
c9452f9
Revert name change
JCQuintas Sep 2, 2024
1e0fe2c
Remove default undefined
JCQuintas Sep 4, 2024
d17ced2
Remove pie type ref
JCQuintas Sep 4, 2024
ec96652
Apply suggestions from code review
JCQuintas Sep 4, 2024
ddbb4ce
Merge commit '2e711dda3a5f86a3bfa4da7f9bcf104979f57a29' into 12344-ch…
JCQuintas Sep 4, 2024
23da223
Make itemid optional
JCQuintas Sep 5, 2024
9268123
Merge commit 'ff6866d66b36e095506b4023f7c8326da8b31643' into 12344-ch…
JCQuintas Sep 11, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
148 changes: 148 additions & 0 deletions docs/data/charts/legend/LegendClickNoSnap.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import * as React from 'react';
import Stack from '@mui/material/Stack';
import Box from '@mui/material/Box';
import Typography from '@mui/material/Typography';
import IconButton from '@mui/material/IconButton';
import UndoOutlinedIcon from '@mui/icons-material/UndoOutlined';

import { ChartsLegend, PiecewiseColorLegend } from '@mui/x-charts/ChartsLegend';

import { HighlightedCode } from '@mui/docs/HighlightedCode';
import { ResponsiveChartContainer } from '@mui/x-charts/ResponsiveChartContainer';

const pieSeries = [
{
type: 'pie',
id: 'series-1',
label: 'Series 1',
data: [
{ label: 'Pie A', id: 'P1-A', value: 400 },
{ label: 'Pie B', id: 'P2-B', value: 300 },
],
},
];

const barSeries = [
{
type: 'bar',
id: 'series-1',
label: 'Series 1',
data: [0, 1, 2],
},
{
type: 'bar',
id: 'series-2',
label: 'Series 2',
data: [0, 1, 2],
},
];

const lineSeries = [
{
type: 'line',
id: 'series-1',
label: 'Series 1',
data: [0, 1, 2],
},
{
type: 'line',
id: 'series-2',
label: 'Series 2',
data: [0, 1, 2],
},
];

export default function LegendClickNoSnap() {
const [itemData, setItemData] = React.useState();

return (
<Stack
direction={{ xs: 'column', md: 'row' }}
spacing={{ xs: 0, md: 4 }}
sx={{ width: '100%' }}
>
<Box sx={{ flexGrow: 1 }}>
<Typography>Chart Legend</Typography>
<ResponsiveChartContainer series={barSeries} width={400} height={60}>
<ChartsLegend
direction="row"
position={{
horizontal: 'left',
vertical: 'top',
}}
onItemClick={(event, context, index) => setItemData([context, index])}
/>
</ResponsiveChartContainer>
<Typography>Pie Chart Legend</Typography>
<ResponsiveChartContainer series={pieSeries} width={400} height={60}>
<ChartsLegend
direction="row"
position={{
horizontal: 'left',
vertical: 'top',
}}
onItemClick={(event, context, index) => setItemData([context, index])}
/>
</ResponsiveChartContainer>
<Typography>Pie Chart Legend</Typography>
<ResponsiveChartContainer
series={lineSeries}
width={400}
height={60}
xAxis={[
{
scaleType: 'linear',
data: [0, 1, 3],
disableLine: true,
colorMap: {
type: 'piecewise',
thresholds: [0, 2],
colors: ['blue', 'gray', 'red'],
},
},
]}
>
<PiecewiseColorLegend
direction="row"
position={{
horizontal: 'left',
vertical: 'top',
}}
axisDirection="x"
onItemClick={(event, context, index) => setItemData([context, index])}
/>
</ResponsiveChartContainer>
</Box>

<Stack direction="column" sx={{ width: { xs: '100%', md: '40%' } }}>
<Box
sx={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
}}
>
<Typography>Click on the chart</Typography>
<IconButton
aria-label="reset"
size="small"
onClick={() => {
setItemData(null);
}}
>
<UndoOutlinedIcon fontSize="small" />
</IconButton>
</Box>
<HighlightedCode
code={`// Index from item click: ${itemData ? itemData[1] : ''}

// Context from item click
${itemData ? JSON.stringify(itemData[0], null, 2) : '// The data will appear here'}
`}
language="json"
copyButtonHidden
/>
</Stack>
</Stack>
);
}
18 changes: 18 additions & 0 deletions docs/data/charts/legend/legend.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,3 +111,21 @@ labelFormatter = ({ min, max, formattedMin, formattedMax }) => string | null;
```

{{"demo": "PiecewiseInteractiveDemoNoSnap.js", "hideToolbar": true, "bg": "playground"}}

## Click event

You can pass an `onItemClick` function to the `ChartsLegend` or `PiecewiseColorLegend` components to handle click events.
They both provide the following signature.

```js
const clickHandler = (
event, // The click event.
context, // An object that identifies the clicked item.
index, // The index of the clicked item.
) => {};
```

The `context` object contains different properties depending on the legend type.
Click the legend items to see their content.

{{"demo": "LegendClickNoSnap.js"}}
13 changes: 13 additions & 0 deletions docs/pages/x/api/charts/charts-legend.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@
"itemMarkWidth": { "type": { "name": "number" }, "default": "20" },
"labelStyle": { "type": { "name": "object" }, "default": "theme.typography.subtitle1" },
"markGap": { "type": { "name": "number" }, "default": "5" },
"onItemClick": {
"type": { "name": "func" },
"signature": {
"type": "function(event: React.MouseEvent<SVGRectElement, MouseEvent>, legendItem: SeriesLegendItemContext, index: number) => void",
"describedArgs": ["event", "legendItem", "index"]
}
},
"padding": {
"type": {
"name": "union",
Expand Down Expand Up @@ -49,6 +56,12 @@
"description": "Styles applied to the legend with column layout.",
"isGlobal": false
},
{
"key": "itemBackground",
"className": "MuiChartsLegend-itemBackground",
"description": "Styles applied to the item background.",
"isGlobal": false
},
{
"key": "label",
"className": "MuiChartsLegend-label",
Expand Down
13 changes: 13 additions & 0 deletions docs/pages/x/api/charts/default-charts-legend.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@
"itemMarkWidth": { "type": { "name": "number" }, "default": "20" },
"labelStyle": { "type": { "name": "object" }, "default": "theme.typography.subtitle1" },
"markGap": { "type": { "name": "number" }, "default": "5" },
"onItemClick": {
"type": { "name": "func" },
"signature": {
"type": "function(event: React.MouseEvent<SVGRectElement, MouseEvent>, legendItem: SeriesLegendItemContext, index: number) => void",
"describedArgs": ["event", "legendItem", "index"]
}
},
"padding": {
"type": {
"name": "union",
Expand All @@ -39,6 +46,12 @@
"description": "Styles applied to the legend with column layout.",
"isGlobal": false
},
{
"key": "itemBackground",
"className": "MuiDefaultChartsLegend-itemBackground",
"description": "Styles applied to the item background.",
"isGlobal": false
},
{
"key": "label",
"className": "MuiDefaultChartsLegend-label",
Expand Down
2 changes: 1 addition & 1 deletion docs/pages/x/api/charts/pie-chart.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
"legend": {
"type": {
"name": "shape",
"description": "{ classes?: object, direction?: 'column'<br>&#124;&nbsp;'row', hidden?: bool, itemGap?: number, itemMarkHeight?: number, itemMarkWidth?: number, labelStyle?: object, markGap?: number, padding?: number<br>&#124;&nbsp;{ bottom?: number, left?: number, right?: number, top?: number }, position?: { horizontal: 'left'<br>&#124;&nbsp;'middle'<br>&#124;&nbsp;'right', vertical: 'bottom'<br>&#124;&nbsp;'middle'<br>&#124;&nbsp;'top' }, slotProps?: object, slots?: object }"
"description": "{ classes?: object, direction?: 'column'<br>&#124;&nbsp;'row', hidden?: bool, itemGap?: number, itemMarkHeight?: number, itemMarkWidth?: number, labelStyle?: object, markGap?: number, onItemClick?: func, padding?: number<br>&#124;&nbsp;{ bottom?: number, left?: number, right?: number, top?: number }, position?: { horizontal: 'left'<br>&#124;&nbsp;'middle'<br>&#124;&nbsp;'right', vertical: 'bottom'<br>&#124;&nbsp;'middle'<br>&#124;&nbsp;'top' }, slotProps?: object, slots?: object }"
},
"default": "{ direction: 'column', position: { vertical: 'middle', horizontal: 'right' } }",
"deprecated": true,
Expand Down
13 changes: 13 additions & 0 deletions docs/pages/x/api/charts/piecewise-color-legend.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@
},
"labelStyle": { "type": { "name": "object" }, "default": "theme.typography.subtitle1" },
"markGap": { "type": { "name": "number" }, "default": "5" },
"onItemClick": {
"type": { "name": "func" },
"signature": {
"type": "function(event: React.MouseEvent<SVGRectElement, MouseEvent>, legendItem: PiecewiseColorLegendItemContext, index: number) => void",
"describedArgs": ["event", "legendItem", "index"]
}
},
"padding": {
"type": {
"name": "union",
Expand All @@ -56,6 +63,12 @@
"description": "Styles applied to the legend with column layout.",
"isGlobal": false
},
{
"key": "itemBackground",
"className": "MuiPiecewiseColorLegend-itemBackground",
"description": "Styles applied to the item background.",
"isGlobal": false
},
{
"key": "label",
"className": "MuiPiecewiseColorLegend-label",
Expand Down
12 changes: 12 additions & 0 deletions docs/translations/api-docs/charts/charts-legend/charts-legend.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@
"itemMarkWidth": { "description": "Width of the item mark (in px)." },
"labelStyle": { "description": "Style applied to legend labels." },
"markGap": { "description": "Space between the mark and the label (in px)." },
"onItemClick": {
"description": "Callback fired when a legend item is clicked.",
"typeDescriptions": {
"event": "The click event.",
"legendItem": "The legend item data.",
"index": "The index of the clicked legend item."
}
},
"padding": {
"description": "Legend padding (in px). Can either be a single number, or an object with top, left, bottom, right properties."
},
Expand All @@ -23,6 +31,10 @@
"description": "Styles applied to {{nodeName}}.",
"nodeName": "the legend with column layout"
},
"itemBackground": {
"description": "Styles applied to {{nodeName}}.",
"nodeName": "the item background"
},
"label": { "description": "Styles applied to {{nodeName}}.", "nodeName": "the series label" },
"mark": { "description": "Styles applied to {{nodeName}}.", "nodeName": "series mark element" },
"root": { "description": "Styles applied to the root element." },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@
"itemMarkWidth": { "description": "Width of the item mark (in px)." },
"labelStyle": { "description": "Style applied to legend labels." },
"markGap": { "description": "Space between the mark and the label (in px)." },
"onItemClick": {
"description": "Callback fired when a legend item is clicked.",
"typeDescriptions": {
"event": "The click event.",
"legendItem": "The legend item data.",
"index": "The index of the clicked legend item."
}
},
"padding": {
"description": "Legend padding (in px). Can either be a single number, or an object with top, left, bottom, right properties."
},
Expand All @@ -21,6 +29,10 @@
"description": "Styles applied to {{nodeName}}.",
"nodeName": "the legend with column layout"
},
"itemBackground": {
"description": "Styles applied to {{nodeName}}.",
"nodeName": "the item background"
},
"label": { "description": "Styles applied to {{nodeName}}.", "nodeName": "the series label" },
"mark": { "description": "Styles applied to {{nodeName}}.", "nodeName": "series mark element" },
"root": { "description": "Styles applied to the root element." },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@
},
"labelStyle": { "description": "Style applied to legend labels." },
"markGap": { "description": "Space between the mark and the label (in px)." },
"onItemClick": {
"description": "Callback fired when a legend item is clicked.",
"typeDescriptions": {
"event": "The click event.",
"legendItem": "The legend item data.",
"index": "The index of the clicked legend item."
}
},
"padding": {
"description": "Legend padding (in px). Can either be a single number, or an object with top, left, bottom, right properties."
},
Expand All @@ -39,6 +47,10 @@
"description": "Styles applied to {{nodeName}}.",
"nodeName": "the legend with column layout"
},
"itemBackground": {
"description": "Styles applied to {{nodeName}}.",
"nodeName": "the item background"
},
"label": { "description": "Styles applied to {{nodeName}}.", "nodeName": "the series label" },
"mark": { "description": "Styles applied to {{nodeName}}.", "nodeName": "series mark element" },
"root": { "description": "Styles applied to the root element." },
Expand Down
1 change: 1 addition & 0 deletions packages/x-charts-pro/src/BarChartPro/BarChartPro.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ BarChartPro.propTypes = {
itemMarkWidth: PropTypes.number,
labelStyle: PropTypes.object,
markGap: PropTypes.number,
onItemClick: PropTypes.func,
padding: PropTypes.oneOfType([
PropTypes.number,
PropTypes.shape({
Expand Down
1 change: 1 addition & 0 deletions packages/x-charts-pro/src/LineChartPro/LineChartPro.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ LineChartPro.propTypes = {
itemMarkWidth: PropTypes.number,
labelStyle: PropTypes.object,
markGap: PropTypes.number,
onItemClick: PropTypes.func,
padding: PropTypes.oneOfType([
PropTypes.number,
PropTypes.shape({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ ScatterChartPro.propTypes = {
itemMarkWidth: PropTypes.number,
labelStyle: PropTypes.object,
markGap: PropTypes.number,
onItemClick: PropTypes.func,
padding: PropTypes.oneOfType([
PropTypes.number,
PropTypes.shape({
Expand Down
1 change: 1 addition & 0 deletions packages/x-charts/src/BarChart/BarChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ BarChart.propTypes = {
itemMarkWidth: PropTypes.number,
labelStyle: PropTypes.object,
markGap: PropTypes.number,
onItemClick: PropTypes.func,
padding: PropTypes.oneOfType([
PropTypes.number,
PropTypes.shape({
Expand Down
4 changes: 3 additions & 1 deletion packages/x-charts/src/BarChart/legend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ const legendGetter: LegendGetter<'bar'> = (params) => {
}

acc.push({
id: seriesId,
seriesId,
color: series[seriesId].color,
label: formattedLabel,
id: seriesId,
});

return acc;
}, [] as LegendItemParams[]);
};
Expand Down
Loading