Skip to content

Commit 6116287

Browse files
committed
Fix light mode
1 parent ba1647b commit 6116287

6 files changed

Lines changed: 149 additions & 108 deletions

File tree

‎frontend/src/components/OHLCChart.tsx‎

Lines changed: 56 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import React, { useEffect, useRef, useState, forwardRef, useImperativeHandle } from "react";
2+
import { useTheme } from "./ThemeProvider";
23
import type {
34
IChartingLibraryWidget,
45
ChartingLibraryWidgetOptions,
@@ -101,6 +102,9 @@ const OHLCChart = forwardRef<OHLCChartRef, OHLCChartProps>(
101102
predictionProjections = [],
102103
onSymbolChange,
103104
}, ref) => {
105+
const { theme } = useTheme();
106+
const isDark = theme === 'dark';
107+
104108
const containerRef = useRef<HTMLDivElement>(null);
105109
const widgetRef = useRef<IChartingLibraryWidget | null>(null);
106110
const containerIdRef = useRef<string>(
@@ -275,8 +279,6 @@ const OHLCChart = forwardRef<OHLCChartRef, OHLCChartProps>(
275279
],
276280
enabled_features: [
277281
"study_templates" as any,
278-
"save_chart_properties_to_local_storage" as any,
279-
"use_localstorage_for_settings" as any,
280282
"left_toolbar" as any,
281283
],
282284
charts_storage_url: "https://saveload.tradingview.com",
@@ -286,33 +288,27 @@ const OHLCChart = forwardRef<OHLCChartRef, OHLCChartProps>(
286288
fullscreen: false,
287289
autosize: true,
288290
studies_overrides: {},
289-
theme: "dark",
291+
theme: isDark ? "dark" : "light",
290292
timezone: "Etc/UTC",
291-
toolbar_bg: "#1E222D",
293+
toolbar_bg: isDark ? "#1E222D" : "#F5F5F5",
292294
loading_screen: {
293-
backgroundColor: "#0D1421",
295+
backgroundColor: isDark ? "#0D1421" : "#FFFFFF",
294296
foregroundColor: "#2962FF",
295297
},
296298
overrides: {
297-
"paneProperties.background": "#0D1421",
299+
"paneProperties.background": isDark ? "#0D1421" : "#FFFFFF",
298300
"paneProperties.backgroundType": "solid",
299-
"paneProperties.vertGridProperties.color": "#2A2E39",
300-
"paneProperties.horzGridProperties.color": "#2A2E39",
301-
"mainSeriesProperties.style": 2, // Candlestick
302-
"mainSeriesProperties.candleStyle.upColor":
303-
bullishColor || "#089981",
304-
"mainSeriesProperties.candleStyle.downColor":
305-
bearishColor || "#F23645",
306-
"mainSeriesProperties.candleStyle.borderUpColor":
307-
bullishColor || "#089981",
308-
"mainSeriesProperties.candleStyle.borderDownColor":
309-
bearishColor || "#F23645",
310-
"mainSeriesProperties.candleStyle.wickUpColor":
311-
bullishColor || "#089981",
312-
"mainSeriesProperties.candleStyle.wickDownColor":
313-
bearishColor || "#F23645",
314-
"scalesProperties.textColor": "#787B86",
315-
"scalesProperties.lineColor": "#2A2E39",
301+
"paneProperties.vertGridProperties.color": isDark ? "#2A2E39" : "#E0E3EB",
302+
"paneProperties.horzGridProperties.color": isDark ? "#2A2E39" : "#E0E3EB",
303+
"mainSeriesProperties.style": 2,
304+
"mainSeriesProperties.candleStyle.upColor": bullishColor || "#089981",
305+
"mainSeriesProperties.candleStyle.downColor": bearishColor || "#F23645",
306+
"mainSeriesProperties.candleStyle.borderUpColor": bullishColor || "#089981",
307+
"mainSeriesProperties.candleStyle.borderDownColor": bearishColor || "#F23645",
308+
"mainSeriesProperties.candleStyle.wickUpColor": bullishColor || "#089981",
309+
"mainSeriesProperties.candleStyle.wickDownColor": bearishColor || "#F23645",
310+
"scalesProperties.textColor": isDark ? "#787B86" : "#555555",
311+
"scalesProperties.lineColor": isDark ? "#2A2E39" : "#E0E3EB",
316312
},
317313
};
318314
// Create the chart widget
@@ -322,6 +318,21 @@ widgetRef.current = new TradingView.widget(widgetOptions);
322318
widgetRef.current.onChartReady(() => {
323319
console.log("[OHLCChart] Chart ready, attaching projection manager");
324320

321+
// Force theme overrides after localStorage restore
322+
try {
323+
const chart = widgetRef.current?.chart() as any
324+
if (chart) {
325+
chart.applyOverrides({
326+
'paneProperties.background': isDark ? '#0D1421' : '#FFFFFF',
327+
'paneProperties.backgroundType': 'solid',
328+
'paneProperties.vertGridProperties.color': isDark ? '#2A2E39' : '#E0E3EB',
329+
'paneProperties.horzGridProperties.color': isDark ? '#2A2E39' : '#E0E3EB',
330+
'scalesProperties.textColor': isDark ? '#787B86' : '#555555',
331+
'scalesProperties.lineColor': isDark ? '#2A2E39' : '#E0E3EB',
332+
})
333+
}
334+
} catch { /* ignore */ }
335+
325336
// Listen for symbol changes in TradingView
326337
if (onSymbolChange) {
327338
widgetRef.current!.activeChart().onSymbolChanged().subscribe(null, (() => {
@@ -488,12 +499,34 @@ widgetRef.current = new TradingView.widget(widgetOptions);
488499
height,
489500
bullishColor,
490501
bearishColor,
502+
isDark,
491503
projectionSettings.strategyName,
492504
projectionSettings.params,
493505
projectionSettings.horizon,
494506
projectionSettings.mode,
495507
]);
496508

509+
// Apply theme to existing widget without full reinit
510+
useEffect(() => {
511+
if (!widgetRef.current) return;
512+
try {
513+
(widgetRef.current as any).changeTheme(isDark ? 'dark' : 'light').then(() => {
514+
const chart = widgetRef.current?.chart() as any
515+
if (!chart) return
516+
chart.applyOverrides({
517+
'paneProperties.background': isDark ? '#0D1421' : '#FFFFFF',
518+
'paneProperties.backgroundType': 'solid',
519+
'paneProperties.vertGridProperties.color': isDark ? '#2A2E39' : '#E0E3EB',
520+
'paneProperties.horzGridProperties.color': isDark ? '#2A2E39' : '#E0E3EB',
521+
'scalesProperties.textColor': isDark ? '#787B86' : '#555555',
522+
'scalesProperties.lineColor': isDark ? '#2A2E39' : '#E0E3EB',
523+
})
524+
})
525+
} catch {
526+
// changeTheme not available on this widget version — full reinit handles it
527+
}
528+
}, [isDark])
529+
497530
// Update prediction settings when props change
498531
useEffect(() => {
499532
setPredictionSettings({

‎frontend/src/components/ui/button.tsx‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@ const buttonVariants = cva(
1313
destructive:
1414
"bg-destructive text-destructive-foreground hover:bg-tv-red-hover shadow-tv-sm",
1515
outline:
16-
"border border-tv-border-secondary bg-transparent hover:bg-tv-bg-hover hover:border-tv-border-hover",
16+
"border border-border bg-transparent hover:bg-tv-bg-hover hover:border-tv-border-hover",
1717
secondary:
18-
"bg-secondary text-secondary-foreground hover:bg-tv-bg-tertiary",
19-
ghost: "hover:bg-tv-bg-hover hover:text-foreground",
18+
"bg-secondary text-secondary-foreground hover:bg-muted",
19+
ghost: "hover:bg-accent hover:text-foreground",
2020
link: "text-primary underline-offset-4 hover:underline hover:text-tv-blue-hover",
2121
success: "bg-success text-success-foreground hover:bg-tv-green-hover shadow-tv-sm",
2222
},

‎frontend/src/components/ui/card.tsx‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const Card = React.forwardRef<
99
<div
1010
ref={ref}
1111
className={cn(
12-
"rounded border border-tv-border-primary bg-card text-card-foreground shadow-tv-sm transition-tv hover:border-tv-border-secondary",
12+
"rounded border border-border bg-card text-card-foreground shadow-tv-sm transition-tv hover:border-tv-border-secondary",
1313
className
1414
)}
1515
{...props}
@@ -36,7 +36,7 @@ const CardTitle = React.forwardRef<
3636
<h3
3737
ref={ref}
3838
className={cn(
39-
"text-base font-semibold leading-none tracking-tight text-tv-text-primary",
39+
"text-base font-semibold leading-none tracking-tight text-foreground",
4040
className
4141
)}
4242
{...props}
@@ -50,7 +50,7 @@ const CardDescription = React.forwardRef<
5050
>(({ className, ...props }, ref) => (
5151
<p
5252
ref={ref}
53-
className={cn("text-xs text-tv-text-secondary", className)}
53+
className={cn("text-xs text-muted-foreground", className)}
5454
{...props}
5555
/>
5656
))

‎frontend/src/components/ui/input.tsx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
1111
<input
1212
type={type}
1313
className={cn(
14-
"flex h-8 w-full rounded border border-tv-border-secondary bg-tv-bg-tertiary px-3 py-1.5 text-sm text-tv-text-primary transition-tv file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-tv-text-tertiary focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary focus-visible:border-primary hover:border-tv-border-hover disabled:cursor-not-allowed disabled:opacity-40",
14+
"flex h-8 w-full rounded border border-input bg-background px-3 py-1.5 text-sm text-foreground transition-tv file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary focus-visible:border-primary hover:border-tv-border-hover disabled:cursor-not-allowed disabled:opacity-40",
1515
className
1616
)}
1717
ref={ref}

‎frontend/src/styles/tailwind.css‎

Lines changed: 63 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
@layer base {
66
:root {
7-
/* Light theme (optional) */
87
--background: 0 0% 100%;
98
--foreground: 222.2 84% 4.9%;
109
--card: 0 0% 100%;
@@ -25,39 +24,55 @@
2524
--input: 214.3 31.8% 91.4%;
2625
--ring: 221.2 83.2% 53.3%;
2726
--radius: 0.25rem;
27+
28+
--tv-bg-primary: 0 0% 100%;
29+
--tv-bg-secondary: 220 14% 96%;
30+
--tv-bg-tertiary: 220 13% 91%;
31+
--tv-bg-elevated: 0 0% 99%;
32+
--tv-bg-hover: 221 83% 95%;
33+
--tv-border-primary: 214 32% 88%;
34+
--tv-border-secondary: 214 32% 82%;
35+
--tv-border-hover: 214 32% 70%;
36+
--tv-text-primary: 222 47% 11%;
37+
--tv-text-secondary: 215 14% 40%;
38+
--tv-text-tertiary: 215 14% 58%;
39+
--tv-text-disabled: 215 14% 74%;
2840
}
2941

3042
.dark {
31-
/* TradingView-inspired dark theme */
32-
--background: 217 33% 7%; /* #0D1421 */
33-
--foreground: 225 11% 85%; /* #D1D4DC */
34-
35-
--card: 220 20% 18%; /* #1E222D */
36-
--card-foreground: 225 11% 85%; /* #D1D4DC */
37-
38-
--popover: 217 33% 7%; /* #0D1421 */
43+
--background: 217 33% 7%;
44+
--foreground: 225 11% 85%;
45+
--card: 220 20% 18%;
46+
--card-foreground: 225 11% 85%;
47+
--popover: 217 33% 7%;
3948
--popover-foreground: 225 11% 85%;
40-
41-
--primary: 221 100% 57%; /* #2962FF */
49+
--primary: 221 100% 57%;
4250
--primary-foreground: 0 0% 100%;
43-
44-
--secondary: 220 17% 20%; /* #2A2E39 */
51+
--secondary: 220 17% 20%;
4552
--secondary-foreground: 225 11% 85%;
46-
47-
--muted: 220 17% 20%; /* #2A2E39 */
48-
--muted-foreground: 225 8% 51%; /* #787B86 */
49-
50-
--accent: 220 17% 20%; /* #2A2E39 */
53+
--muted: 220 17% 20%;
54+
--muted-foreground: 225 8% 51%;
55+
--accent: 220 17% 20%;
5156
--accent-foreground: 225 11% 85%;
52-
53-
--destructive: 354 85% 57%; /* #F23645 */
57+
--destructive: 354 85% 57%;
5458
--destructive-foreground: 0 0% 100%;
55-
56-
--border: 220 17% 20%; /* #2A2E39 */
59+
--border: 220 17% 20%;
5760
--input: 220 17% 20%;
58-
--ring: 221 100% 57%; /* #2962FF */
59-
61+
--ring: 221 100% 57%;
6062
--radius: 0.25rem;
63+
64+
--tv-bg-primary: 217 33% 7%;
65+
--tv-bg-secondary: 220 20% 18%;
66+
--tv-bg-tertiary: 220 17% 20%;
67+
--tv-bg-elevated: 219 30% 10%;
68+
--tv-bg-hover: 221 83% 20%;
69+
--tv-border-primary: 220 17% 20%;
70+
--tv-border-secondary: 220 15% 26%;
71+
--tv-border-hover: 220 13% 32%;
72+
--tv-text-primary: 225 11% 85%;
73+
--tv-text-secondary: 225 8% 51%;
74+
--tv-text-tertiary: 220 12% 34%;
75+
--tv-text-disabled: 220 15% 26%;
6176
}
6277
}
6378

@@ -93,12 +108,12 @@ html, body, #root {
93108
}
94109

95110
::-webkit-scrollbar-thumb {
96-
background: #2A2E39;
111+
background: hsl(var(--tv-border-secondary));
97112
border-radius: 4px;
98113
}
99114

100115
::-webkit-scrollbar-thumb:hover {
101-
background: #363A45;
116+
background: hsl(var(--tv-border-hover));
102117
}
103118

104119
::-webkit-scrollbar-corner {
@@ -108,7 +123,7 @@ html, body, #root {
108123
/* Firefox scrollbar */
109124
* {
110125
scrollbar-width: thin;
111-
scrollbar-color: #2A2E39 transparent;
126+
scrollbar-color: hsl(var(--tv-border-secondary)) transparent;
112127
}
113128

114129
/* Smooth transitions - more subtle than before */
@@ -120,10 +135,9 @@ html, body, #root {
120135
}
121136
}
122137

123-
/* Selection color */
124138
::selection {
125-
background-color: rgba(41, 98, 255, 0.3);
126-
color: #D1D4DC;
139+
background-color: hsl(var(--primary) / 0.25);
140+
color: hsl(var(--foreground));
127141
}
128142

129143
/* Remove default button styles */
@@ -134,35 +148,35 @@ button {
134148
/* Utility classes for TradingView styling */
135149
@layer utilities {
136150
.text-tv-primary {
137-
color: #D1D4DC;
151+
color: hsl(var(--tv-text-primary));
138152
}
139-
153+
140154
.text-tv-secondary {
141-
color: #787B86;
155+
color: hsl(var(--tv-text-secondary));
142156
}
143-
157+
144158
.text-tv-tertiary {
145-
color: #50535E;
159+
color: hsl(var(--tv-text-tertiary));
146160
}
147-
161+
148162
.bg-tv-primary {
149-
background-color: #0D1421;
163+
background-color: hsl(var(--tv-bg-primary));
150164
}
151-
165+
152166
.bg-tv-secondary {
153-
background-color: #1E222D;
167+
background-color: hsl(var(--tv-bg-secondary));
154168
}
155-
169+
156170
.bg-tv-tertiary {
157-
background-color: #2A2E39;
171+
background-color: hsl(var(--tv-bg-tertiary));
158172
}
159-
173+
160174
.border-tv-primary {
161-
border-color: #2A2E39;
175+
border-color: hsl(var(--tv-border-primary));
162176
}
163-
177+
164178
.border-tv-secondary {
165-
border-color: #363A45;
179+
border-color: hsl(var(--tv-border-secondary));
166180
}
167181

168182
/* Compact spacing for TradingView feel */
@@ -193,10 +207,10 @@ button {
193207
animation: shimmer 2s linear infinite;
194208
background: linear-gradient(
195209
to right,
196-
#1E222D 0%,
197-
#2A2E39 20%,
198-
#1E222D 40%,
199-
#1E222D 100%
210+
hsl(var(--tv-bg-secondary)) 0%,
211+
hsl(var(--tv-bg-tertiary)) 20%,
212+
hsl(var(--tv-bg-secondary)) 40%,
213+
hsl(var(--tv-bg-secondary)) 100%
200214
);
201215
background-size: 1000px 100%;
202216
}

0 commit comments

Comments
 (0)