Karan6124 commited on
Commit
7b917d0
·
1 Parent(s): 13152e7

fix: replace default chart tooltip with custom premium glassmorphic tooltip

Browse files

- StockChart.tsx: Implemented CustomTooltip component for hover interactions, rendering Open/High/Low/Close data and active SMA/EMA overlays in color-coded, high-contrast, fully readable typography.

frontend/src/components/StockChart.tsx CHANGED
@@ -80,6 +80,80 @@ const CandlestickBar = (props: any) => {
80
  );
81
  };
82
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83
  export default function StockChart({ activeTicker, chartData, activeStats, chartRange, onRangeChange }: StockChartProps) {
84
  const currentPrice = chartData.length > 0 ? chartData[chartData.length - 1].price : null;
85
 
@@ -315,15 +389,7 @@ export default function StockChart({ activeTicker, chartData, activeStats, chart
315
  tickLine={false}
316
  />
317
 
318
- <Tooltip
319
- contentStyle={{
320
- background: '#0d101b',
321
- borderColor: '#2e303a',
322
- borderRadius: '8px',
323
- color: '#fff',
324
- fontSize: '12px'
325
- }}
326
- />
327
 
328
  {/* Primary Chart Type Representation */}
329
  {chartType === 'line' ? (
 
80
  );
81
  };
82
 
83
+ // Custom premium Tooltip component for stock chart hover stats
84
+ const CustomTooltip = ({ active, payload, label }: any) => {
85
+ if (active && payload && payload.length) {
86
+ const data = payload[0].payload;
87
+ const isCandle = data.open !== undefined && data.close !== undefined;
88
+
89
+ return (
90
+ <div style={{
91
+ background: 'rgba(13, 16, 27, 0.9)',
92
+ backdropFilter: 'blur(12px)',
93
+ border: '1px solid rgba(255, 255, 255, 0.1)',
94
+ borderRadius: '8px',
95
+ padding: '12px 16px',
96
+ boxShadow: '0 12px 24px rgba(0, 0, 0, 0.6)',
97
+ color: '#fff',
98
+ fontSize: '12px',
99
+ fontFamily: 'inherit',
100
+ minWidth: '160px'
101
+ }}>
102
+ <div style={{ fontWeight: 600, color: 'var(--text-secondary)', borderBottom: '1px solid rgba(255,255,255,0.08)', paddingBottom: '6px', marginBottom: '8px' }}>
103
+ {label}
104
+ </div>
105
+
106
+ {isCandle ? (
107
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '4px' }}>
108
+ <div style={{ display: 'flex', justifyContent: 'space-between', gap: '16px' }}>
109
+ <span style={{ color: 'var(--text-muted)' }}>Open</span>
110
+ <span style={{ fontWeight: 600, color: '#fff' }}>${data.open.toFixed(2)}</span>
111
+ </div>
112
+ <div style={{ display: 'flex', justifyContent: 'space-between', gap: '16px' }}>
113
+ <span style={{ color: 'var(--text-muted)' }}>High</span>
114
+ <span style={{ fontWeight: 600, color: '#10b981' }}>${data.high?.toFixed(2)}</span>
115
+ </div>
116
+ <div style={{ display: 'flex', justifyContent: 'space-between', gap: '16px' }}>
117
+ <span style={{ color: 'var(--text-muted)' }}>Low</span>
118
+ <span style={{ fontWeight: 600, color: '#ef4444' }}>${data.low?.toFixed(2)}</span>
119
+ </div>
120
+ <div style={{ display: 'flex', justifyContent: 'space-between', gap: '16px' }}>
121
+ <span style={{ color: 'var(--text-muted)' }}>Close</span>
122
+ <span style={{ fontWeight: 600, color: '#fff' }}>${data.close.toFixed(2)}</span>
123
+ </div>
124
+ </div>
125
+ ) : (
126
+ <div style={{ display: 'flex', justifyContent: 'space-between', gap: '16px' }}>
127
+ <span style={{ color: 'var(--text-muted)' }}>Price</span>
128
+ <span style={{ fontWeight: 600, color: 'var(--neon-cyan)' }}>${data.price.toFixed(2)}</span>
129
+ </div>
130
+ )}
131
+
132
+ {payload.map((entry: any, index: number) => {
133
+ if (entry.dataKey === 'sma' && entry.value !== undefined && entry.value !== null) {
134
+ return (
135
+ <div key={`sma-${index}`} style={{ display: 'flex', justifyContent: 'space-between', gap: '16px', color: 'var(--neon-violet)', borderTop: '1px solid rgba(255,255,255,0.06)', paddingTop: '4px', marginTop: '4px' }}>
136
+ <span>SMA 20</span>
137
+ <span style={{ fontWeight: 600 }}>${entry.value.toFixed(2)}</span>
138
+ </div>
139
+ );
140
+ }
141
+ if (entry.dataKey === 'ema' && entry.value !== undefined && entry.value !== null) {
142
+ return (
143
+ <div key={`ema-${index}`} style={{ display: 'flex', justifyContent: 'space-between', gap: '16px', color: '#fb923c', borderTop: '1px solid rgba(255,255,255,0.06)', paddingTop: '4px', marginTop: '4px' }}>
144
+ <span>EMA 20</span>
145
+ <span style={{ fontWeight: 600 }}>${entry.value.toFixed(2)}</span>
146
+ </div>
147
+ );
148
+ }
149
+ return null;
150
+ })}
151
+ </div>
152
+ );
153
+ }
154
+ return null;
155
+ };
156
+
157
  export default function StockChart({ activeTicker, chartData, activeStats, chartRange, onRangeChange }: StockChartProps) {
158
  const currentPrice = chartData.length > 0 ? chartData[chartData.length - 1].price : null;
159
 
 
389
  tickLine={false}
390
  />
391
 
392
+ <Tooltip content={<CustomTooltip />} />
 
 
 
 
 
 
 
 
393
 
394
  {/* Primary Chart Type Representation */}
395
  {chartType === 'line' ? (