-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Open
Labels
scope: chartsChanges related to the charts.Changes related to the charts.status: waiting for maintainerThese issues haven't been looked at yet by a maintainer.These issues haven't been looked at yet by a maintainer.support: premium standardSupport request from a Premium standard plan user. https://mui.com/legal/technical-support-sla.Support request from a Premium standard plan user. https://mui.com/legal/technical-support-sla.
Description
Summary
I have a feature where I display multiple vendors on a line chart based on which vendors are checked. Additionally, the user can select a specific vendor. When a vendor is selected, I want the tooltip on the line chart to display only the details for that selected vendor, instead of showing all the vendors.
Here is my code.
Here BMW is selected, I want all vendor lines to remain visible on the chart, but the tooltip should display information only for the BMW vendor. Additionally, when I hover over any vendor line, that line should be highlighted, while all other lines should appear dimmed.
import React, { useMemo } from 'react';
import { LineChart } from '@mui/x-charts/LineChart';
const baseColors = [
'#393b79',
'#1f77b4',
'#ff7f0e',
'#d62728',
'#9467bd',
'#8c564b',
'#e377c2',
'#7f7f7f',
'#bcbd22',
'#17becf',
'#637939',
'#8c6d31',
'#843c39',
'#7b4173',
'#3182bd',
'#2ca02c',
'#31a354',
'#756bb1',
'#636363',
'#e6550d',
];
const getMonthName = (dateStr: string) => {
const [year, month] = dateStr.split('-');
const monthIndex = parseInt(month, 10) - 1;
const monthsShort = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
return `${monthsShort[monthIndex]} ${year}`;
};
const getLastXMonths = (latestMonth: string, count: number): string[] => {
const [year, month] = latestMonth.split('-').map(Number);
const months: string[] = [];
for (let i = count - 1; i >= 0; i--) {
const d = new Date(year, month - 1 - i, 1);
months.push(`${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}`);
}
return months;
};
interface VendorLineChartProps {
setHoveredIndex: React.Dispatch<React.SetStateAction<number | null>>;
hoveredIndex: number | null;
}
const VendorLineChart: React.FC<VendorLineChartProps> = ({ setHoveredIndex, hoveredIndex }) => {
const vendorChartDataList = [
{
id: '7ed8633d-16bf-44e7-8419-10352cb672a0',
vendorName: 'BMW',
graphData: [
{
month: '2024-12',
count: 0,
amount: 0,
},
{
month: '2025-01',
count: 0,
amount: 0,
},
{
month: '2025-02',
count: 0,
amount: 0,
},
{
month: '2025-03',
count: 6,
amount: 0,
},
{
month: '2025-04',
count: 167,
amount: 0,
},
{
month: '2025-05',
count: 16897,
amount: 0,
},
{
month: '2025-06',
count: 161,
amount: 0,
},
{
month: '2025-07',
count: 257,
amount: 0,
},
{
month: '2025-08',
count: 272,
amount: 0,
},
{
month: '2025-09',
count: 262,
amount: 0,
},
{
month: '2025-10',
count: 12,
amount: 0,
},
{
month: '2025-11',
count: 60,
amount: 0,
},
{
month: '2025-12',
count: 24,
amount: 0,
},
],
},
{
id: 'c90b92db-6ba1-408a-a7fe-2d3a900acff8',
vendorName: 'Volkswagon',
graphData: [
{
month: '2024-12',
count: 0,
amount: 0,
},
{
month: '2025-01',
count: 1,
amount: 0,
},
{
month: '2025-02',
count: 0,
amount: 0,
},
{
month: '2025-03',
count: 0,
amount: 0,
},
{
month: '2025-04',
count: 130925,
amount: 0,
},
{
month: '2025-05',
count: 1,
amount: 0,
},
{
month: '2025-06',
count: 0,
amount: 0,
},
{
month: '2025-07',
count: 12,
amount: 0,
},
{
month: '2025-08',
count: 24,
amount: 0,
},
{
month: '2025-09',
count: 0,
amount: 0,
},
{
month: '2025-10',
count: 1022,
amount: 0,
},
{
month: '2025-11',
count: 0,
amount: 0,
},
{
month: '2025-12',
count: 12,
amount: 0,
},
],
},
{
id: 'b5c7572c-2f87-45c4-af29-b21862cb2bda',
vendorName: 'Suzuki',
graphData: [
{
month: '2024-12',
count: 0,
amount: 0,
},
{
month: '2025-01',
count: 0,
amount: 0,
},
{
month: '2025-02',
count: 0,
amount: 0,
},
{
month: '2025-03',
count: 0,
amount: 0,
},
{
month: '2025-04',
count: 0,
amount: 0,
},
{
month: '2025-05',
count: 0,
amount: 0,
},
{
month: '2025-06',
count: 12,
amount: 0,
},
{
month: '2025-07',
count: 0,
amount: 0,
},
{
month: '2025-08',
count: 12,
amount: 0,
},
{
month: '2025-09',
count: 12,
amount: 0,
},
{
month: '2025-10',
count: 24,
amount: 0,
},
{
month: '2025-11',
count: 0,
amount: 0,
},
{
month: '2025-12',
count: 0,
amount: 0,
},
],
},
{
id: 'c453d2db-1542-4a5e-9297-9419243a6136',
vendorName: 'Tata',
graphData: [
{
month: '2024-12',
count: 0,
amount: 0,
},
{
month: '2025-01',
count: 0,
amount: 0,
},
{
month: '2025-02',
count: 0,
amount: 0,
},
{
month: '2025-03',
count: 0,
amount: 0,
},
{
month: '2025-04',
count: 0,
amount: 0,
},
{
month: '2025-05',
count: 0,
amount: 0,
},
{
month: '2025-06',
count: 0,
amount: 0,
},
{
month: '2025-07',
count: 24,
amount: 0,
},
{
month: '2025-08',
count: 0,
amount: 0,
},
{
month: '2025-09',
count: 0,
amount: 0,
},
{
month: '2025-10',
count: 12,
amount: 0,
},
{
month: '2025-11',
count: 24,
amount: 0,
},
{
month: '2025-12',
count: 24,
amount: 0,
},
],
},
{
id: '25f38a99-e46c-4d93-95d3-25a5df209068',
vendorName: 'Audi',
graphData: [
{
month: '2024-12',
count: 0,
amount: 0,
},
{
month: '2025-01',
count: 0,
amount: 0,
},
{
month: '2025-02',
count: 0,
amount: 0,
},
{
month: '2025-03',
count: 0,
amount: 0,
},
{
month: '2025-04',
count: 0,
amount: 0,
},
{
month: '2025-05',
count: 0,
amount: 0,
},
{
month: '2025-06',
count: 0,
amount: 0,
},
{
month: '2025-07',
count: 0,
amount: 0,
},
{
month: '2025-08',
count: 0,
amount: 0,
},
{
month: '2025-09',
count: 0,
amount: 0,
},
{
month: '2025-10',
count: 2,
amount: 0,
},
{
month: '2025-11',
count: 0,
amount: 0,
},
{
month: '2025-12',
count: 0,
amount: 0,
},
],
},
];
const checkedVendors = [
'7ed8633d-16bf-44e7-8419-10352cb672a0',
'c90b92db-6ba1-408a-a7fe-2d3a900acff8',
'b5c7572c-2f87-45c4-af29-b21862cb2bda',
'c453d2db-1542-4a5e-9297-9419243a6136',
'25f38a99-e46c-4d93-95d3-25a5df209068',
];
const selectedVendorId = '7ed8633d-16bf-44e7-8419-10352cb672a0';
const chartData = useMemo(() => {
if (!vendorChartDataList?.length) {
return { labels: [], series: [] };
}
let latestMonth = '1900-01';
vendorChartDataList.forEach((v) =>
v.graphData.forEach((g) => {
if (g.month > latestMonth) latestMonth = g.month;
})
);
const allMonths = getLastXMonths(latestMonth, 13);
const labels = allMonths.map(getMonthName);
// 🔑 PRIORITY LOGIC
const vendorsToShow =
checkedVendors.length > 0
? vendorChartDataList.filter((v) => checkedVendors.includes(v.id))
: vendorChartDataList;
const series = vendorsToShow.map((v) => ({
id: v.id,
label: v.vendorName,
data: allMonths.map((m) => v.graphData.find((g) => g.month === m)?.count ?? 0),
}));
return { labels, series };
}, [vendorChartDataList, checkedVendors, selectedVendorId]);
return (
<>
<LineChart
xAxis={[
{
id: 'months',
data: chartData.labels,
tickLabelStyle: { fontSize: '0.6rem', fontWeight: 600 },
scaleType: 'point',
},
]}
series={chartData.series.map((s, i) => {
const isSelected = selectedVendorId === s.id;
const isHovered = hoveredIndex === i;
const shouldHighlight = selectedVendorId ? isSelected : hoveredIndex === null || isHovered;
return {
id: s.id,
label: s.label,
data: s.data,
color: shouldHighlight ? baseColors[i % baseColors.length] : '#ccc',
lineWidth: shouldHighlight ? 3 : 1.5,
opacity: shouldHighlight ? 1 : 0.4,
};
})}
yAxis={[
{
tickLabelStyle: { fontSize: '0.6rem', fontWeight: 600 },
label: '<-- Orders -->',
width: 50,
},
]}
slots={{
legend: () => null,
}}
margin={{ left: 0, right: 0, bottom: 0 }}
sx={{
width: '100%',
'& .MuiLineElement-root': { strokeWidth: 2 },
'& .MuiMarkElement-root': { display: 'none' },
}}
/>
</>
);
};
export default VendorLineChart;
Examples
No response
Motivation
No response
Search keywords: Custom tooltip for line chart
Order ID: 86305
Metadata
Metadata
Assignees
Labels
scope: chartsChanges related to the charts.Changes related to the charts.status: waiting for maintainerThese issues haven't been looked at yet by a maintainer.These issues haven't been looked at yet by a maintainer.support: premium standardSupport request from a Premium standard plan user. https://mui.com/legal/technical-support-sla.Support request from a Premium standard plan user. https://mui.com/legal/technical-support-sla.