Skip to content

Commit 88988d8

Browse files
authored
Fix ReClamm x-axis and add tooltip (#6)
* Fix chart interval and add tooltip * Fix price bar chart
1 parent a24df3e commit 88988d8

File tree

3 files changed

+94
-29
lines changed

3 files changed

+94
-29
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import * as d3 from 'd3';
2+
3+
export const Tooltip = () => {
4+
const tooltip = d3
5+
.select('body')
6+
.append('div')
7+
.attr('class', 'tooltip')
8+
.style('opacity', 0)
9+
.style('position', 'absolute')
10+
.style('background-color', 'white')
11+
.style('border', '1px solid #ddd')
12+
.style('border-radius', '4px')
13+
.style('padding', '8px')
14+
.style('pointer-events', 'none')
15+
.style('font-size', '12px');
16+
17+
return tooltip;
18+
};

client/src/pool-types/reclamm/ReClammChart.tsx

Lines changed: 58 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React, { useRef, useEffect, useMemo } from 'react';
22
import * as d3 from 'd3';
33
import { calculateLowerMargin, calculateUpperMargin } from './ReClammMath';
4+
import { Tooltip } from '../../components/chart/Tooltip';
45

56
interface ReClammChartProps {
67
realTimeBalanceA: number;
@@ -42,14 +43,17 @@ export const ReClammChart: React.FC<ReClammChartProps> = ({
4243
const xForPointB =
4344
realTimeInvariant / realTimeVirtualBalances.virtualBalanceB;
4445

46+
const firstChartX =
47+
realTimeVirtualBalances.virtualBalanceA -
48+
MARGIN * (xForPointB - realTimeVirtualBalances.virtualBalanceA);
49+
const lastChartX =
50+
xForPointB +
51+
MARGIN * (xForPointB - realTimeVirtualBalances.virtualBalanceA);
52+
const chartXRange = lastChartX - firstChartX;
53+
4554
// Create regular curve points
4655
const curvePoints = Array.from({ length: NUM_POINTS }, (_, i) => {
47-
const x =
48-
(1 - MARGIN) * realTimeVirtualBalances.virtualBalanceA +
49-
(i *
50-
((1 + MARGIN) * xForPointB -
51-
(1 - MARGIN) * realTimeVirtualBalances.virtualBalanceA)) /
52-
NUM_POINTS;
56+
const x = firstChartX + (i * chartXRange) / NUM_POINTS;
5357
const y = realTimeInvariant / x;
5458

5559
return { x, y };
@@ -348,6 +352,8 @@ export const ReClammChart: React.FC<ReClammChartProps> = ({
348352
.attr('stroke-width', 2)
349353
.attr('d', line);
350354

355+
const tooltip = Tooltip();
356+
351357
// Add special points (min/max prices) for both real-time and current
352358
svg
353359
.selectAll('.point-price')
@@ -358,23 +364,29 @@ export const ReClammChart: React.FC<ReClammChartProps> = ({
358364
.attr('cx', d => xScale(d.x))
359365
.attr('cy', d => yScale(d.y))
360366
.attr('r', 5)
361-
.attr('fill', 'red');
362-
363-
// Add tooltip div
364-
const tooltip = d3
365-
.select('body')
366-
.append('div')
367-
.attr('class', 'tooltip')
368-
.style('opacity', 0)
369-
.style('position', 'absolute')
370-
.style('background-color', 'white')
371-
.style('border', '1px solid #ddd')
372-
.style('border-radius', '4px')
373-
.style('padding', '8px')
374-
.style('pointer-events', 'none')
375-
.style('font-size', '12px');
367+
.attr('fill', 'red')
368+
.on('mouseover', (event, d) => {
369+
tooltip
370+
.style('opacity', 1)
371+
.html(
372+
`Balance A: ${(
373+
d.x - realTimeVirtualBalances.virtualBalanceA
374+
).toFixed(
375+
2
376+
)}<br/>Balance B: ${(d.y - realTimeVirtualBalances.virtualBalanceB).toFixed(2)}`
377+
)
378+
.style('left', event.pageX + 10 + 'px')
379+
.style('top', event.pageY - 10 + 'px');
380+
})
381+
.on('mouseout', () => {
382+
tooltip.style('opacity', 0);
383+
})
384+
.on('mousemove', event => {
385+
tooltip
386+
.style('left', event.pageX + 10 + 'px')
387+
.style('top', event.pageY - 10 + 'px');
388+
});
376389

377-
// Modify the balance points section
378390
svg
379391
.selectAll('.point-balance')
380392
.data(specialPoints.slice(4, 6)) // Real-time and current balances
@@ -389,9 +401,9 @@ export const ReClammChart: React.FC<ReClammChartProps> = ({
389401
tooltip
390402
.style('opacity', 1)
391403
.html(
392-
`Real Balance A: ${realTimeBalanceA.toFixed(
404+
`Balance A: ${realTimeBalanceA.toFixed(
393405
2
394-
)}<br/>Real Balance B: ${realTimeBalanceB.toFixed(2)}`
406+
)}<br/>Balance B: ${realTimeBalanceB.toFixed(2)}`
395407
)
396408
.style('left', event.pageX + 10 + 'px')
397409
.style('top', event.pageY - 10 + 'px');
@@ -415,7 +427,28 @@ export const ReClammChart: React.FC<ReClammChartProps> = ({
415427
.attr('cx', d => xScale(d.x))
416428
.attr('cy', d => yScale(d.y))
417429
.attr('r', 5)
418-
.attr('fill', 'blue');
430+
.attr('fill', 'blue')
431+
.on('mouseover', (event, d) => {
432+
tooltip
433+
.style('opacity', 1)
434+
.html(
435+
`Balance A: ${(
436+
d.x - realTimeVirtualBalances.virtualBalanceA
437+
).toFixed(
438+
2
439+
)}<br/>Balance B: ${(d.y - realTimeVirtualBalances.virtualBalanceB).toFixed(2)}`
440+
)
441+
.style('left', event.pageX + 10 + 'px')
442+
.style('top', event.pageY - 10 + 'px');
443+
})
444+
.on('mouseout', () => {
445+
tooltip.style('opacity', 0);
446+
})
447+
.on('mousemove', event => {
448+
tooltip
449+
.style('left', event.pageX + 10 + 'px')
450+
.style('top', event.pageY - 10 + 'px');
451+
});
419452

420453
// Add axis labels
421454
svg

client/src/pool-types/reclamm/ReClammPriceBar.tsx

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -151,13 +151,20 @@ export const ReClammPriceBar: React.FC<ReClammPriceBarProps> = ({
151151
priceData.forEach((d, _) => {
152152
const x = xScale(d.value);
153153

154-
// Add vertical line
154+
// Add vertical line with different lengths based on color
155+
const lineY2 =
156+
d.color === 'blue'
157+
? chartHeight * 0.7
158+
: d.color === 'red'
159+
? chartHeight * 0.7 + 15
160+
: chartHeight * 0.7;
161+
155162
chart
156163
.append('line')
157164
.attr('x1', x)
158165
.attr('y1', chartHeight * 0.3)
159166
.attr('x2', x)
160-
.attr('y2', chartHeight * 0.7)
167+
.attr('y2', lineY2)
161168
.attr('stroke', d.color)
162169
.attr('stroke-width', 3)
163170
.attr('opacity', 0.8);
@@ -172,11 +179,18 @@ export const ReClammPriceBar: React.FC<ReClammPriceBarProps> = ({
172179
.attr('stroke', '#fff')
173180
.attr('stroke-width', 2);
174181

175-
// Add value label on top
182+
// Add value label with different positions based on color
183+
const labelY =
184+
d.color === 'green'
185+
? chartHeight * 0.2 // Green stays above
186+
: d.color === 'red'
187+
? chartHeight * 0.8 + 20 // Red at blue's level
188+
: chartHeight * 0.8 + 5; // Blue at red's level
189+
176190
chart
177191
.append('text')
178192
.attr('x', x)
179-
.attr('y', chartHeight * 0.2)
193+
.attr('y', labelY)
180194
.attr('text-anchor', 'middle')
181195
.attr('font-size', '12px')
182196
.attr('fill', d.color)

0 commit comments

Comments
 (0)