Skip to content

Commit 4a2eb1d

Browse files
authored
Add CustomLegend component for interactive legend
1 parent e184110 commit 4a2eb1d

File tree

1 file changed

+161
-0
lines changed

1 file changed

+161
-0
lines changed

index.tsx

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
import { Box, Flex, Text, Tooltip } from '@chakra-ui/react';
2+
import { useEffect, useState } from 'react';
3+
4+
export default function CustomLegend({
5+
barProps,
6+
setBarProps,
7+
keys,
8+
w,
9+
...props
10+
}: any) {
11+
const showReset = !keys.every((item: any) => barProps[item.key]);
12+
const [hasShownTooltip, setHasShownTooltip] = useState(false);
13+
const [showTooltip, setShowTooltip] = useState(false);
14+
15+
const resetSelected = () => {
16+
setBarProps(
17+
keys?.reduce(
18+
(a: any, { key }: any) => {
19+
a[key] = true;
20+
return a;
21+
},
22+
{
23+
hover: null,
24+
}
25+
)
26+
);
27+
};
28+
29+
return (
30+
<Box flexDirection={'column'} padding={'0 20px'} w={w ? w : 220}>
31+
<Tooltip
32+
label={'Double-click on legend to isolate a single metric.'}
33+
isOpen={showTooltip}
34+
placement="top"
35+
w={170}
36+
fontSize={'xs'}
37+
>
38+
<Text
39+
fontWeight={600}
40+
fontSize={'xs'}
41+
textDecor={'underline'}
42+
w={'fit-content'}
43+
mb={1}
44+
onClick={() => {
45+
if (!showReset) {
46+
return;
47+
}
48+
resetSelected();
49+
}}
50+
visibility={showReset ? 'visible' : 'hidden'}
51+
cursor={'pointer'}
52+
>
53+
Reset
54+
</Text>
55+
</Tooltip>
56+
{keys?.map((entry: any) => {
57+
const isLine = ['line_chart', 'dashed_line_chart'].includes(
58+
entry?.chartType
59+
);
60+
return (
61+
<Flex
62+
key={entry?.key}
63+
align={'center'}
64+
w={'fit-content'}
65+
cursor={'pointer'}
66+
onDoubleClick={() => {
67+
setBarProps(
68+
keys?.reduce(
69+
(a: any, { key }: any) => {
70+
a[key] = entry?.key === key ? true : false;
71+
return a;
72+
},
73+
{
74+
hover: null,
75+
}
76+
)
77+
);
78+
}}
79+
onClick={() => {
80+
if (!hasShownTooltip) {
81+
setHasShownTooltip(true);
82+
setShowTooltip(true);
83+
setTimeout(() => {
84+
setShowTooltip(false);
85+
}, 1500);
86+
}
87+
88+
setBarProps((barProps: any) => {
89+
return {
90+
...barProps,
91+
[entry?.key]: !barProps[entry?.key],
92+
hover: null,
93+
};
94+
});
95+
}}
96+
onMouseEnter={() => {
97+
if (!barProps[entry?.key]) {
98+
return;
99+
}
100+
setBarProps((barProps: any) => {
101+
return { ...barProps, hover: entry.key };
102+
});
103+
}}
104+
onMouseLeave={() => {
105+
setBarProps((barProps: any) => {
106+
return { ...barProps, hover: null };
107+
});
108+
}}
109+
>
110+
{isLine ? (
111+
<svg width="20" height="3" style={{ marginRight: '5px' }}>
112+
<line
113+
x1="0"
114+
y1="1.5"
115+
x2="20"
116+
y2="1.5"
117+
stroke={barProps[entry?.key] ? entry?.color : 'grey'}
118+
strokeWidth="3"
119+
strokeDasharray={
120+
entry?.chartType === 'dashed_line_chart' ? '2 2' : 'none'
121+
}
122+
/>
123+
</svg>
124+
) : (
125+
<svg width="20" height="20" style={{ marginRight: '5px' }}>
126+
<circle
127+
cx="10"
128+
cy="10"
129+
r="5"
130+
fill={barProps[entry?.key] ? entry?.color : 'grey'}
131+
fillOpacity={
132+
entry?.chartType === 'dashed_bar_chart' ? 0.2 : 1
133+
}
134+
stroke={
135+
entry?.chartType === 'dashed_bar_chart'
136+
? entry?.color
137+
: 'none'
138+
}
139+
strokeDasharray={
140+
entry?.chartType === 'dashed_bar_chart' ? '2 2' : 'none'
141+
}
142+
/>
143+
</svg>
144+
)}
145+
<Text
146+
_hover={
147+
barProps[entry?.key]
148+
? { color: entry?.color, fontWeight: 600 }
149+
: { color: 'grey' }
150+
}
151+
color={barProps[entry?.key] ? entry?.color : 'grey'}
152+
decoration={barProps[entry?.key] ? 'auto' : 'line-through'}
153+
>
154+
{entry?.name}
155+
</Text>
156+
</Flex>
157+
);
158+
})}
159+
</Box>
160+
);
161+
}

0 commit comments

Comments
 (0)