Skip to content

Commit 2d10558

Browse files
committed
2 parents a9e7c7e + 5c4ec79 commit 2d10558

File tree

6 files changed

+848
-7
lines changed

6 files changed

+848
-7
lines changed

packages/data-viz/src/core/StackedBarChart/StackedBarChart.types.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,36 @@ export interface StackedBarChartProps extends HTMLAttributes<HTMLDivElement> {
9494
selectedIndices: number[],
9595
selectedData: StackedBarChartDataItem[]
9696
) => void;
97+
/**
98+
* Callback when mouse enters a bar segment
99+
*/
100+
onSegmentMouseEnter?: (item: StackedBarChartDataItem, index: number) => void;
101+
/**
102+
* Callback when mouse leaves a bar segment
103+
*/
104+
onSegmentMouseLeave?: (item: StackedBarChartDataItem, index: number) => void;
105+
/**
106+
* Callback when mouse enters a legend item
107+
*/
108+
onLegendItemMouseEnter?: (
109+
item: StackedBarChartDataItem,
110+
index: number
111+
) => void;
112+
/**
113+
* Callback when mouse leaves a legend item
114+
*/
115+
onLegendItemMouseLeave?: (
116+
item: StackedBarChartDataItem,
117+
index: number
118+
) => void;
119+
/**
120+
* Callback when a bar segment is clicked
121+
*/
122+
onSegmentClick?: (item: StackedBarChartDataItem, index: number) => void;
123+
/**
124+
* Callback when a legend item is clicked
125+
*/
126+
onLegendItemClick?: (item: StackedBarChartDataItem, index: number) => void;
97127
/**
98128
* Behavior to apply when items are selected
99129
* - "dim": Non-selected segments become semi-transparent (20% opacity)

packages/data-viz/src/core/StackedBarChart/__storybook__/index.stories.tsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { Meta } from "@storybook/react-webpack5";
22
import { StackedBarChart } from "./stories/default";
33
import WithSelectionStory from "./stories/withSelection";
4+
import WithMouseEventsStory from "./stories/withMouseEvents";
45
import { STACKED_BAR_CHART_DATA } from "./constants";
56

67
export default {
@@ -214,6 +215,21 @@ export const CumulativeWithSelectionHideBehavior = {
214215
},
215216
};
216217

218+
export const WithMouseEvents = {
219+
render: WithMouseEventsStory,
220+
args: {
221+
barHeight: 16,
222+
data: STACKED_BAR_CHART_DATA,
223+
showLegend: true,
224+
showLegendValues: true,
225+
title: "Mouse Events Demo",
226+
width: "360px",
227+
colorGeneratorOptions: {
228+
...DEFAULT_COLOR_GENERATOR_OPTIONS,
229+
},
230+
},
231+
};
232+
217233
// Test
218234

219235
export const Test = {
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
import { useState } from "react";
2+
import { Args } from "@storybook/react-webpack5";
3+
import RawStackedBarChart from "../../index";
4+
import { StackedBarChartDataItem } from "../../StackedBarChart.types";
5+
import { useTheme } from "@mui/material";
6+
7+
export default function WithMouseEventsStory(args: Args): JSX.Element {
8+
const { data, ...rest } = args;
9+
const [hoveredSegment, setHoveredSegment] = useState<{
10+
item: StackedBarChartDataItem;
11+
index: number;
12+
source: "segment" | "legend";
13+
} | null>(null);
14+
const [eventLog, setEventLog] = useState<string[]>([]);
15+
const theme = useTheme();
16+
17+
const addToLog = (message: string) => {
18+
setEventLog((prev) => [message, ...prev].slice(0, 10)); // Keep last 10 events
19+
};
20+
21+
const handleSegmentMouseEnter = (
22+
item: StackedBarChartDataItem,
23+
index: number
24+
) => {
25+
setHoveredSegment({ item, index, source: "segment" });
26+
addToLog(`Segment Enter: ${item.name} (index ${index})`);
27+
console.log("Segment Mouse Enter:", { item, index });
28+
};
29+
30+
const handleSegmentMouseLeave = (
31+
item: StackedBarChartDataItem,
32+
index: number
33+
) => {
34+
setHoveredSegment(null);
35+
addToLog(`Segment Leave: ${item.name} (index ${index})`);
36+
console.log("Segment Mouse Leave:", { item, index });
37+
};
38+
39+
const handleLegendItemMouseEnter = (
40+
item: StackedBarChartDataItem,
41+
index: number
42+
) => {
43+
setHoveredSegment({ item, index, source: "legend" });
44+
addToLog(`Legend Enter: ${item.name} (index ${index})`);
45+
console.log("Legend Mouse Enter:", { item, index });
46+
};
47+
48+
const handleLegendItemMouseLeave = (
49+
item: StackedBarChartDataItem,
50+
index: number
51+
) => {
52+
setHoveredSegment(null);
53+
addToLog(`Legend Leave: ${item.name} (index ${index})`);
54+
console.log("Legend Mouse Leave:", { item, index });
55+
};
56+
57+
const handleSegmentClick = (item: StackedBarChartDataItem, index: number) => {
58+
addToLog(`Segment Click: ${item.name} (index ${index})`);
59+
console.log("Segment Click:", { item, index });
60+
};
61+
62+
const handleLegendItemClick = (
63+
item: StackedBarChartDataItem,
64+
index: number
65+
) => {
66+
addToLog(`Legend Click: ${item.name} (index ${index})`);
67+
console.log("Legend Click:", { item, index });
68+
};
69+
70+
return (
71+
<div
72+
style={{
73+
margin: 150,
74+
}}
75+
>
76+
<RawStackedBarChart
77+
{...rest}
78+
data={data}
79+
onSegmentMouseEnter={handleSegmentMouseEnter}
80+
onSegmentMouseLeave={handleSegmentMouseLeave}
81+
onLegendItemMouseEnter={handleLegendItemMouseEnter}
82+
onLegendItemMouseLeave={handleLegendItemMouseLeave}
83+
onSegmentClick={handleSegmentClick}
84+
onLegendItemClick={handleLegendItemClick}
85+
/>
86+
87+
<div
88+
style={{
89+
marginTop: "40px",
90+
display: "flex",
91+
gap: "16px",
92+
flexGrow: 1,
93+
alignItems: "flex-start",
94+
}}
95+
>
96+
<div
97+
style={{
98+
padding: "16px",
99+
backgroundColor: theme?.palette?.sds?.base?.backgroundTertiary,
100+
borderRadius: "8px",
101+
marginBottom: "16px",
102+
}}
103+
>
104+
<h3 style={{ margin: "0 0 12px 0", fontSize: "14px" }}>
105+
Current Hover State (Hover over a bar segment or legend item):
106+
</h3>
107+
<div>
108+
<div>
109+
<strong>Name:</strong> {hoveredSegment?.item.name || "-"}
110+
</div>
111+
<div>
112+
<strong>Value:</strong> {hoveredSegment?.item.value || "-"}
113+
</div>
114+
<div>
115+
<strong>Index:</strong> {hoveredSegment?.index || "-"}
116+
</div>
117+
<div>
118+
<strong>Source:</strong> {hoveredSegment?.source || "-"}
119+
</div>
120+
121+
<div>
122+
<strong>Custom Color:</strong>{" "}
123+
{hoveredSegment?.item.color ? (
124+
<>
125+
<span
126+
style={{
127+
display: "inline-block",
128+
width: "12px",
129+
height: "12px",
130+
backgroundColor: hoveredSegment.item.color,
131+
borderRadius: "2px",
132+
margin: "0 4px 0 2px",
133+
verticalAlign: "middle",
134+
}}
135+
/>
136+
<span>{hoveredSegment.item.color}</span>
137+
</>
138+
) : (
139+
<span>-</span>
140+
)}
141+
</div>
142+
</div>
143+
</div>
144+
145+
<div
146+
style={{
147+
padding: "16px",
148+
backgroundColor: theme?.palette?.sds?.base?.backgroundTertiary,
149+
borderRadius: "8px",
150+
maxHeight: "400px",
151+
overflow: "auto",
152+
}}
153+
>
154+
<h3 style={{ margin: "0 0 12px 0", fontSize: "14px" }}>
155+
Event Log (last 10 events):
156+
</h3>
157+
{eventLog.length === 0 ? (
158+
<div style={{ fontSize: "12px" }}>
159+
No events yet. Hover or click on segments or legend items to see
160+
events.
161+
</div>
162+
) : (
163+
<ul
164+
style={{
165+
margin: 0,
166+
padding: "0 0 0 20px",
167+
fontSize: "12px",
168+
fontFamily: "monospace",
169+
}}
170+
>
171+
{eventLog.map((event, index) => (
172+
<li key={index} style={{ marginBottom: "4px" }}>
173+
{event}
174+
</li>
175+
))}
176+
</ul>
177+
)}
178+
</div>
179+
</div>
180+
</div>
181+
);
182+
}

0 commit comments

Comments
 (0)