Skip to content
This repository was archived by the owner on Dec 10, 2025. It is now read-only.

Commit e522817

Browse files
committed
add tooltip for box
1 parent 1b95923 commit e522817

File tree

8 files changed

+424
-20
lines changed

8 files changed

+424
-20
lines changed

frontend/src/components/elevator/car.tsx

Lines changed: 70 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import Matter from "matter-js";
22
import { useEffect, useRef, useState } from "preact/hooks";
33
import {
44
BlockHeader,
5+
Network,
56
Transaction,
67
TransactionType,
78
TransactionTypeEnum,
@@ -15,6 +16,8 @@ import {
1516
import { useAtomValue } from "jotai";
1617
import { ChainTheme, chainThemeAtom } from "../../states/atoms";
1718
import ElevatorCapacity from "./capacity";
19+
import { JSX } from "preact/jsx-runtime";
20+
import { bodyToScreenPosition, createTooltipContent } from "../../util/scene";
1821

1922
export interface ElevatorCarProp {
2023
transactions: Transaction[];
@@ -27,6 +30,13 @@ const ElevatorCar: React.FC<ElevatorCarProp> = (props) => {
2730
const { transactions, blockHeader, setFromDoorClosing } = props;
2831

2932
const [doorClosing, setDoorClosing] = useState(false);
33+
const [tooltipContent, setTooltipContent] = useState<JSX.Element | null>(
34+
null,
35+
);
36+
const [tooltipPosition, setTooltipPosition] = useState<{
37+
x: number;
38+
y: number;
39+
} | null>(null);
3040

3141
const boxRef = useRef(null);
3242
const canvasRef = useRef(null);
@@ -59,6 +69,15 @@ const ElevatorCar: React.FC<ElevatorCarProp> = (props) => {
5969
},
6070
});
6171

72+
// create mouse constraint on hover
73+
const mouse = Matter.Mouse.create(render.canvas);
74+
const mouseConstraint = Matter.MouseConstraint.create(engine, {
75+
mouse,
76+
constraint: {
77+
render: { visible: false },
78+
},
79+
});
80+
6281
// create two boxes and a ground
6382
const txBoxes = transactions.map((tx, i) => {
6483
const size = transactionSquareSize(tx.size);
@@ -72,8 +91,15 @@ const ElevatorCar: React.FC<ElevatorCarProp> = (props) => {
7291
strokeStyle: "black",
7392
lineWidth: 3,
7493
},
94+
tooltip: {
95+
txHash: tx.tx_hash,
96+
txSize: +tx.size,
97+
txType: +tx.type,
98+
txFee: +tx.fee,
99+
FirstSeenInPool: tx.enter_pool_at,
100+
},
101+
label: tx.tx_hash,
75102
});
76-
box.label = tx.tx_hash;
77103
return box;
78104
});
79105

@@ -118,7 +144,13 @@ const ElevatorCar: React.FC<ElevatorCarProp> = (props) => {
118144
);
119145

120146
// add all of the bodies to the world
121-
Composite.add(engine.world, [...txBoxes, ground, wall1, wall2]);
147+
Composite.add(engine.world, [
148+
...txBoxes,
149+
ground,
150+
wall1,
151+
wall2,
152+
mouseConstraint,
153+
]);
122154

123155
// run the renderer
124156
Render.run(render);
@@ -143,6 +175,28 @@ const ElevatorCar: React.FC<ElevatorCarProp> = (props) => {
143175
context.fillText(`${+fee}`, x - 30, y);
144176
}
145177
});
178+
179+
// listen to mouse hover event
180+
Matter.Events.on(mouseConstraint, "mousemove", (event) => {
181+
const hoveredBody = Matter.Query.point(
182+
Matter.Composite.allBodies(engine.world),
183+
event.mouse.position,
184+
)[0];
185+
186+
if (hoveredBody?.tooltip) {
187+
const pos = bodyToScreenPosition(hoveredBody);
188+
setTooltipContent(
189+
createTooltipContent(
190+
hoveredBody.tooltip,
191+
chainTheme as unknown as Network,
192+
),
193+
);
194+
setTooltipPosition(pos);
195+
} else {
196+
setTooltipContent(null);
197+
setTooltipPosition(null);
198+
}
199+
});
146200
}
147201

148202
useEffect(() => {
@@ -186,6 +240,20 @@ const ElevatorCar: React.FC<ElevatorCarProp> = (props) => {
186240
doorClosing ? "closed" : ""
187241
}`}
188242
>
243+
{/* Transaction Box Tooltip 层 */}
244+
{tooltipContent && tooltipPosition && (
245+
<div
246+
className="absolute z-50 p-2 bg-gray-800 text-white rounded-md text-sm whitespace-pre"
247+
style={{
248+
left: `${tooltipPosition.x + 15}px`,
249+
top: `${tooltipPosition.y}px`,
250+
transform: "translateY(-50%)",
251+
}}
252+
>
253+
{tooltipContent}
254+
</div>
255+
)}
256+
189257
<div
190258
className={`m-auto ${bgElevatorSide}`}
191259
id="matter-js-box"

frontend/src/components/pool/committed-line.tsx

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
1-
import { useEffect, useRef } from "preact/hooks";
1+
import { useEffect, useRef, useState } from "preact/hooks";
22
import Matter from "matter-js";
33
import {
4+
Network,
45
Transaction,
56
TransactionType,
67
TransactionTypeEnum,
78
} from "../../service/type";
8-
import { FunctionalComponent } from "preact";
9+
import { FunctionalComponent, JSX } from "preact";
910
import { transactionSquareSize } from "../elevator/util";
11+
import { useAtomValue } from "jotai";
12+
import { chainThemeAtom } from "../../states/atoms";
13+
import { bodyToScreenPosition, createTooltipContent } from "../../util/scene";
1014

1115
export interface CommittedLineProps {
1216
title: string;
@@ -17,6 +21,16 @@ export const CommittedLine: FunctionalComponent<CommittedLineProps> = ({
1721
title,
1822
txs,
1923
}) => {
24+
const chainTheme = useAtomValue(chainThemeAtom);
25+
26+
const [tooltipContent, setTooltipContent] = useState<JSX.Element | null>(
27+
null,
28+
);
29+
const [tooltipPosition, setTooltipPosition] = useState<{
30+
x: number;
31+
y: number;
32+
} | null>(null);
33+
2034
const containerRef = useRef(null);
2135
const canvasRef = useRef(null);
2236
const engineRef = useRef(null);
@@ -64,7 +78,16 @@ export const CommittedLine: FunctionalComponent<CommittedLineProps> = ({
6478
// create two boxes and a ground
6579
const txBoxes = txs.map((tx, i) => createTxBox(tx));
6680

67-
Matter.Composite.add(engine.world, [...txBoxes]);
81+
// create mouse constraint on hover
82+
const mouse = Matter.Mouse.create(render.canvas);
83+
const mouseConstraint = Matter.MouseConstraint.create(engine, {
84+
mouse,
85+
constraint: {
86+
render: { visible: false },
87+
},
88+
});
89+
90+
Matter.Composite.add(engine.world, [...txBoxes, mouseConstraint]);
6891

6992
// run the renderer
7093
Render.run(render);
@@ -74,6 +97,28 @@ export const CommittedLine: FunctionalComponent<CommittedLineProps> = ({
7497

7598
// run the engine
7699
Runner.run(runner, engine);
100+
101+
// listen to mouse hover event
102+
Matter.Events.on(mouseConstraint, "mousemove", (event) => {
103+
const hoveredBody = Matter.Query.point(
104+
Matter.Composite.allBodies(engine.world),
105+
event.mouse.position,
106+
)[0];
107+
108+
if (hoveredBody?.tooltip) {
109+
const pos = bodyToScreenPosition(hoveredBody);
110+
setTooltipContent(
111+
createTooltipContent(
112+
hoveredBody.tooltip,
113+
chainTheme as unknown as Network,
114+
),
115+
);
116+
setTooltipPosition(pos);
117+
} else {
118+
setTooltipContent(null);
119+
setTooltipPosition(null);
120+
}
121+
});
77122
}
78123

79124
useEffect(() => {
@@ -92,6 +137,19 @@ export const CommittedLine: FunctionalComponent<CommittedLineProps> = ({
92137
<img src="/assets/svg/pool-ground.svg" alt="" />
93138
</div>
94139
<canvas className={`z-2 relative`} ref={canvasRef} />
140+
{/* Transaction Box Tooltip 层 */}
141+
{tooltipContent && tooltipPosition && (
142+
<div
143+
className="absolute z-50 p-2 bg-gray-800 text-white rounded-md text-sm whitespace-pre"
144+
style={{
145+
left: `${tooltipPosition.x + 15}px`,
146+
top: `${tooltipPosition.y}px`,
147+
transform: "translateY(-50%)",
148+
}}
149+
>
150+
{tooltipContent}
151+
</div>
152+
)}
95153
</div>
96154
</div>
97155
</div>

frontend/src/components/pool/committing-line.tsx

Lines changed: 76 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
1-
import { useEffect, useRef } from "preact/hooks";
1+
import { useEffect, useRef, useState } from "preact/hooks";
22
import Matter from "matter-js";
33
import {
4+
Network,
45
Transaction,
56
TransactionType,
67
TransactionTypeEnum,
78
} from "../../service/type";
8-
import { FunctionalComponent } from "preact";
9+
import { FunctionalComponent, JSX } from "preact";
910
import { transactionSquareSize } from "../elevator/util";
11+
import { useAtomValue } from "jotai";
12+
import { chainThemeAtom } from "../../states/atoms";
13+
import { bodyToScreenPosition, createTooltipContent } from "../../util/scene";
1014

1115
export interface LineProps {
1216
title: string;
@@ -17,6 +21,16 @@ export const CommittingLine: FunctionalComponent<LineProps> = ({
1721
title,
1822
txs,
1923
}) => {
24+
const chainTheme = useAtomValue(chainThemeAtom);
25+
26+
const [tooltipContent, setTooltipContent] = useState<JSX.Element | null>(
27+
null,
28+
);
29+
const [tooltipPosition, setTooltipPosition] = useState<{
30+
x: number;
31+
y: number;
32+
} | null>(null);
33+
2034
const containerRef = useRef(null);
2135
const canvasRef = useRef(null);
2236
const engineRef = useRef(null);
@@ -34,8 +48,15 @@ export const CommittingLine: FunctionalComponent<LineProps> = ({
3448
strokeStyle: "black",
3549
lineWidth: 3,
3650
},
51+
tooltip: {
52+
txHash: tx.tx_hash,
53+
txSize: +tx.size,
54+
txType: +tx.type,
55+
txFee: +tx.fee,
56+
FirstSeenInPool: tx.enter_pool_at,
57+
},
58+
label: tx.tx_hash,
3759
});
38-
box.label = tx.tx_hash;
3960
return box;
4061
}
4162

@@ -65,6 +86,15 @@ export const CommittingLine: FunctionalComponent<LineProps> = ({
6586
// create two boxes and a ground
6687
const txBoxes = txs.map((tx, i) => createTxBox(tx));
6788

89+
// create mouse constraint on hover
90+
const mouse = Matter.Mouse.create(render.canvas);
91+
const mouseConstraint = Matter.MouseConstraint.create(engine, {
92+
mouse,
93+
constraint: {
94+
render: { visible: false },
95+
},
96+
});
97+
6898
// 添加示例物体
6999
const wall1 = Matter.Bodies.rectangle(width, 0, 1, height * 2, {
70100
isStatic: true,
@@ -87,7 +117,13 @@ export const CommittingLine: FunctionalComponent<LineProps> = ({
87117
},
88118
});
89119

90-
Matter.Composite.add(engine.world, [...txBoxes, ground, wall1, wall2]);
120+
Matter.Composite.add(engine.world, [
121+
...txBoxes,
122+
ground,
123+
wall1,
124+
wall2,
125+
mouseConstraint,
126+
]);
91127

92128
// run the renderer
93129
Render.run(render);
@@ -97,6 +133,28 @@ export const CommittingLine: FunctionalComponent<LineProps> = ({
97133

98134
// run the engine
99135
Runner.run(runner, engine);
136+
137+
// listen to mouse hover event
138+
Matter.Events.on(mouseConstraint, "mousemove", (event) => {
139+
const hoveredBody = Matter.Query.point(
140+
Matter.Composite.allBodies(engine.world),
141+
event.mouse.position,
142+
)[0];
143+
144+
if (hoveredBody?.tooltip) {
145+
const pos = bodyToScreenPosition(hoveredBody);
146+
setTooltipContent(
147+
createTooltipContent(
148+
hoveredBody.tooltip,
149+
chainTheme as unknown as Network,
150+
),
151+
);
152+
setTooltipPosition(pos);
153+
} else {
154+
setTooltipContent(null);
155+
setTooltipPosition(null);
156+
}
157+
});
100158
}
101159

102160
useEffect(() => {
@@ -155,8 +213,21 @@ export const CommittingLine: FunctionalComponent<LineProps> = ({
155213
</div>
156214
</div>
157215

158-
<div ref={containerRef}>
216+
<div className={"relative"} ref={containerRef}>
159217
<canvas ref={canvasRef} />
218+
{/* Transaction Box Tooltip 层 */}
219+
{tooltipContent && tooltipPosition && (
220+
<div
221+
className="absolute z-50 p-2 bg-gray-800 text-white rounded-md text-sm whitespace-pre"
222+
style={{
223+
left: `${tooltipPosition.x + 15}px`,
224+
top: `${tooltipPosition.y}px`,
225+
transform: "translateY(-50%)",
226+
}}
227+
>
228+
{tooltipContent}
229+
</div>
230+
)}
160231
</div>
161232
<div className={"h-[300px] flex items-end"}>
162233
<img src="/assets/svg/line-right.svg" alt="" />

0 commit comments

Comments
 (0)