Skip to content

Commit 07e9497

Browse files
gkorlandCopilot
andcommitted
Fix dark mode graph surfaces
Make the graph canvas and related loading states follow the active theme so dark mode no longer shows bright mismatched surfaces. Validation: - npm --prefix ./app run lint - npm --prefix ./app run build Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent d9c0d49 commit 07e9497

3 files changed

Lines changed: 38 additions & 10 deletions

File tree

app/src/components/chat.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { toast } from "@/components/ui/use-toast";
22
import { Dispatch, FormEvent, SetStateAction, useEffect, useRef, useState } from "react";
3-
import { AlignLeft, ArrowRight, ChevronDown, Lightbulb, Undo2 } from "lucide-react";
3+
import { AlignLeft, ArrowRight, ChevronDown, Lightbulb, Loader2, Undo2 } from "lucide-react";
44
import { Message, MessageTypes, Path, PathData, PATH_COLOR } from "@/lib/utils";
55
import Input from "./Input";
66
import { Graph, GraphData, Node } from "./model";
@@ -616,7 +616,10 @@ export function Chat({ messages, setMessages, query, setQuery, selectedPath, set
616616
)
617617
default: return (
618618
<div key={index} className="flex gap-2">
619-
<img src="/dots.gif" width={100} height={10} alt="Waiting for response" />
619+
<div className="inline-flex items-center gap-2 rounded-md border bg-card px-3 py-2 text-sm text-muted-foreground">
620+
<Loader2 className="h-4 w-4 animate-spin" />
621+
<span>Thinking...</span>
622+
</div>
620623
</div>
621624
)
622625
}

app/src/components/graphView.tsx

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { Fullscreen } from 'lucide-react';
66
import { GraphRef } from '@/lib/utils';
77
import ForceGraph from './ForceGraph';
88
import { GraphLink, GraphNode } from '@falkordb/canvas';
9+
import { useTheme } from './theme-provider';
910

1011
export interface Position {
1112
x: number,
@@ -37,6 +38,14 @@ interface Props {
3738

3839
const NODE_SIZE = 6;
3940
const PADDING = 2;
41+
const LIGHT_CANVAS_BACKGROUND = '#FFFFFF';
42+
const DARK_CANVAS_BACKGROUND = '#1A1A1A';
43+
const LIGHT_CANVAS_FOREGROUND = '#000000';
44+
const DARK_CANVAS_FOREGROUND = '#F5F5F5';
45+
const LIGHT_DIMMED_NODE_FILL = '#E5E5E5';
46+
const DARK_DIMMED_NODE_FILL = '#525252';
47+
const LIGHT_DIMMED_NODE_STROKE = 'gray';
48+
const DARK_DIMMED_NODE_STROKE = '#A3A3A3';
4049

4150
export default function GraphView({
4251
data,
@@ -63,6 +72,12 @@ export default function GraphView({
6372
const lastClick = useRef<{ date: Date, name: string }>({ date: new Date(), name: "" })
6473
const [screenSize, setScreenSize] = useState<number>(0)
6574
const [hoverElement, setHoverElement] = useState<Node | Link | null>()
75+
const { resolvedTheme } = useTheme()
76+
const isDark = resolvedTheme === 'dark'
77+
const canvasBackgroundColor = isDark ? DARK_CANVAS_BACKGROUND : LIGHT_CANVAS_BACKGROUND
78+
const canvasForegroundColor = isDark ? DARK_CANVAS_FOREGROUND : LIGHT_CANVAS_FOREGROUND
79+
const dimmedNodeFillColor = isDark ? DARK_DIMMED_NODE_FILL : LIGHT_DIMMED_NODE_FILL
80+
const dimmedNodeStrokeColor = isDark ? DARK_DIMMED_NODE_STROKE : LIGHT_DIMMED_NODE_STROKE
6681

6782
useEffect(() => {
6883
const handleResize = () => {
@@ -181,8 +196,8 @@ export default function GraphView({
181196
ctx.strokeStyle = PATH_COLOR;
182197
ctx.lineWidth = 1
183198
} else {
184-
ctx.fillStyle = '#E5E5E5';
185-
ctx.strokeStyle = 'gray';
199+
ctx.fillStyle = dimmedNodeFillColor;
200+
ctx.strokeStyle = dimmedNodeStrokeColor;
186201
ctx.lineWidth = 1
187202
}
188203
} else if (isPathResponse === undefined) {
@@ -196,12 +211,12 @@ export default function GraphView({
196211
ctx.lineWidth = 1
197212
} else {
198213
ctx.fillStyle = node.color;
199-
ctx.strokeStyle = 'black';
214+
ctx.strokeStyle = canvasForegroundColor;
200215
ctx.lineWidth = isSelected || isHovered ? 1.5 : 1
201216
}
202217
} else {
203218
ctx.fillStyle = node.color;
204-
ctx.strokeStyle = 'black';
219+
ctx.strokeStyle = canvasForegroundColor;
205220
ctx.lineWidth = isSelected || isHovered ? 1.5 : 1
206221
}
207222

@@ -210,7 +225,7 @@ export default function GraphView({
210225
ctx.stroke();
211226
ctx.fill();
212227

213-
ctx.fillStyle = 'black';
228+
ctx.fillStyle = canvasForegroundColor;
214229
ctx.textAlign = 'center';
215230
ctx.textBaseline = 'middle';
216231
ctx.font = '2px Arial';
@@ -230,7 +245,15 @@ export default function GraphView({
230245

231246
// add label
232247
ctx.fillText(name, node.x, node.y);
233-
}, [selectedObj, selectedObjects, isPathResponse, hoverElement])
248+
}, [
249+
selectedObj,
250+
selectedObjects,
251+
isPathResponse,
252+
hoverElement,
253+
dimmedNodeFillColor,
254+
dimmedNodeStrokeColor,
255+
canvasForegroundColor,
256+
])
234257

235258
const nodePointerAreaPaint = useCallback((node: GraphNode, color: string, ctx: CanvasRenderingContext2D) => {
236259
if (node.x === undefined || node.y === undefined) {
@@ -280,7 +303,9 @@ export default function GraphView({
280303
nodePointerAreaPaint={nodePointerAreaPaint}
281304
linkLineDash={linkLineDash}
282305
cooldownTicks={cooldownTicks}
306+
backgroundColor={canvasBackgroundColor}
307+
foregroundColor={canvasForegroundColor}
283308
/>
284309
</div>
285310
)
286-
}
311+
}

app/src/globals.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@
9898
}
9999

100100
.control-button {
101-
@apply bg-background p-2 rounded-md pointer-events-auto shadow-[0_4px_6px_-1px_rgba(0,0,0,0.1),0_2px_4px_-2px_rgba(0,0,0,0.1)];
101+
@apply bg-card text-card-foreground border border-border p-2 rounded-md pointer-events-auto shadow-[0_4px_6px_-1px_rgba(0,0,0,0.1),0_2px_4px_-2px_rgba(0,0,0,0.1)] hover:bg-accent transition-colors;
102102
}
103103

104104
::-webkit-scrollbar {

0 commit comments

Comments
 (0)