Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion app/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,23 @@
--accent-text: var(--accent-muted);
--hud-line: rgba(153, 69, 255, 0.15);
--hud-line-hover: rgba(153, 69, 255, 0.35);
--cyan-muted: rgba(20, 241, 149, 0.10);

/* Semantic colors — the dark-theme values are neons tuned for dark
surfaces and collapse on white (#14F195 lands at ~1.4:1 — every
positive-PnL numeral, Long fill, and APR figure was near-invisible in
light mode). These darker tones stay legible as TEXT on the light bg
(emerald-600 3.9:1, red-600 4.5:1, amber-700 4.6:1, teal-700 4.9:1)
while keeping the two FILL pairings readable: Long fills pair with
black text (black on #059669 ≈ 5.9:1), Short fills with white text
(white on #DC2626 ≈ 4.6:1). Chart candles use the same values via
useChartTheme's LIGHT_THEME — keep the two in sync. */
--long: #059669;
--short: #DC2626;
--good: #059669;
--critical: #DC2626;
--warning: #B45309;
--cyan: #0F766E;
--cyan-muted: rgba(5, 150, 105, 0.10);

/* Elevation — lighter neutral shadows read correctly on a white surface */
--shadow-xs: 0 1px 2px rgba(13, 14, 21, 0.06);
Expand Down
27 changes: 21 additions & 6 deletions app/components/trade/TradingChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,12 @@ const TradingChartInner: FC<{ slabAddress: string; mintAddress?: string }> = ({
// isolated ~10-line leaf (`LiveMarkPriceLabel`, defined above) that
// subscribes to useLivePrice() itself so only IT re-renders on a tick.
const chartTheme = useChartTheme();
// Ref mirror for the tick handler below — that effect deliberately deps
// only on [slabAddress] (rebuilding the subscription on theme change would
// be wasteful), so it must read the CURRENT theme through a ref or a theme
// flip would leave its closure coloring ticks with the old palette.
const chartThemeRef = useRef(chartTheme);
chartThemeRef.current = chartTheme;
const [chartStyle, setChartStyle] = useChartStylePref();
const [overlayPrefs, setOverlayPref] = useChartOverlayPrefs();
const {
Expand Down Expand Up @@ -716,6 +722,12 @@ const TradingChartInner: FC<{ slabAddress: string; mintAddress?: string }> = ({
rightPriceScale: { borderColor: chartTheme.borderColor },
timeScale: { borderColor: chartTheme.borderColor },
});
// Overlay price lines were created with the previous theme's palette —
// repaint them too (the tick handler recolors the Mark line on the next
// tick anyway, but a flat market shouldn't keep stale-theme lines).
priceLineRef.current?.applyOptions({ color: chartTheme.neutralLine });
liqLineRef.current?.applyOptions({ color: chartTheme.downColor });
entryLineRef.current?.applyOptions({ color: chartTheme.entryLine });
}, [chartTheme]);

// Derive entry price from user account
Expand Down Expand Up @@ -791,7 +803,7 @@ const TradingChartInner: FC<{ slabAddress: string; mintAddress?: string }> = ({
if (initialPriceUsd != null && Number.isFinite(initialPriceUsd)) {
priceLineRef.current = s.createPriceLine({
price: initialPriceUsd,
color: "rgba(255,255,255,0.6)",
color: chartThemeRef.current.neutralLine,
lineWidth: 1,
lineStyle: LineStyle.Dashed,
axisLabelVisible: true,
Expand All @@ -803,7 +815,8 @@ const TradingChartInner: FC<{ slabAddress: string; mintAddress?: string }> = ({
if (overlayPrefs.liq && liqPriceNum != null && liqPriceNum > 0) {
liqLineRef.current = s.createPriceLine({
price: liqPriceNum,
color: "#FF3B5C", // matches --short (canvas can't read CSS vars)
// Per-theme --short equivalent (canvas can't read CSS vars)
color: chartThemeRef.current.downColor,
lineWidth: 2,
lineStyle: LineStyle.Solid,
axisLabelVisible: true,
Expand All @@ -814,7 +827,7 @@ const TradingChartInner: FC<{ slabAddress: string; mintAddress?: string }> = ({
if (overlayPrefs.entry && entryPriceNum != null && entryPriceNum > 0) {
entryLineRef.current = s.createPriceLine({
price: entryPriceNum,
color: "#22d3ee",
color: chartThemeRef.current.entryLine,
lineWidth: 1,
lineStyle: LineStyle.Dashed,
axisLabelVisible: true,
Expand Down Expand Up @@ -1074,10 +1087,12 @@ const TradingChartInner: FC<{ slabAddress: string; mintAddress?: string }> = ({
// long-green/short-red on each tick instead of sitting flat gray —
// same semantic tokens as MarketInfoBar's MarkPrice flash, applied
// here via the price line's own color (canvas can't read CSS vars,
// so these are the literal --long/--short hex values). Holds its
// last color on an exact-equal tick rather than resetting to gray.
// so ChartTheme carries the per-theme --long/--short equivalents;
// read through the ref, this effect deps only on slabAddress). Holds
// its last color on an exact-equal tick rather than resetting to gray.
const prev = prevTickPriceRef.current;
const color = prev == null ? "rgba(255,255,255,0.6)" : usd > prev ? "#14F195" : usd < prev ? "#FF3B5C" : undefined;
const t = chartThemeRef.current;
const color = prev == null ? t.neutralLine : usd > prev ? t.upColor : usd < prev ? t.downColor : undefined;
prevTickPriceRef.current = usd;
priceLineRef.current.applyOptions(color ? { price: usd, color } : { price: usd });
}
Expand Down
16 changes: 13 additions & 3 deletions app/hooks/useChartTheme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ export interface ChartTheme {
downColor: string;
volUpColor: string;
volDownColor: string;
/** Neutral overlay-line color (the Mark price line before any tick). */
neutralLine: string;
/** Entry price overlay line — cyan family, per-theme so it stays legible. */
entryLine: string;
}

const DARK_THEME: ChartTheme = {
Expand All @@ -36,17 +40,23 @@ const DARK_THEME: ChartTheme = {
downColor: "#FF3B5C",
volUpColor: "rgba(20,241,149,0.6)",
volDownColor: "rgba(255,59,92,0.6)",
neutralLine: "rgba(255,255,255,0.6)",
entryLine: "#22d3ee",
};

const LIGHT_THEME: ChartTheme = {
bg: "#FAFAFD",
textColor: "rgba(13,14,21,0.65)",
gridColor: "rgba(0,0,0,0.05)",
borderColor: "rgba(0,0,0,0.10)",
upColor: "#16a34a",
downColor: "#dc2626",
volUpColor: "rgba(22,163,74,0.5)",
// Same values as the light-theme --long/--short tokens in globals.css —
// candles and UI numerals must agree on what "up" green looks like.
upColor: "#059669",
downColor: "#DC2626",
volUpColor: "rgba(5,150,105,0.5)",
volDownColor: "rgba(220,38,38,0.5)",
neutralLine: "rgba(13,14,21,0.55)",
entryLine: "#0F766E",
};

function getThemeFromDOM(): "dark" | "light" {
Expand Down
Loading