Skip to content

Commit 4f83491

Browse files
Fix light mode: use theme-aware CSS variables and darken light palette
Replace hardcoded dark-theme colors in LogView with CSS variables so text is visible in both themes. Darken light mode backgrounds and strengthen text contrast for a less washed-out appearance. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 478bb5b commit 4f83491

2 files changed

Lines changed: 54 additions & 36 deletions

File tree

src/components/LogView.tsx

Lines changed: 40 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ export function LogView({
7373
rateLimitMessage,
7474
}: LogViewProps) {
7575
const worktreePrefix = projectDir && branchName
76-
? `${projectDir}/.ralph/${branchName}-worktree`
76+
? `${projectDir.replace(/\\/g, "/")}/.ralph/${branchName}-worktree`
7777
: undefined;
7878

7979
const parentRef = useRef<HTMLDivElement>(null);
@@ -253,15 +253,33 @@ function IterationHeader({
253253
}
254254

255255
function shortenPath(path: string, worktreePrefix?: string): string {
256-
if (worktreePrefix && path.startsWith(worktreePrefix)) {
257-
return "⌂" + path.slice(worktreePrefix.length);
256+
if (!worktreePrefix) return path;
257+
const normPath = path.replace(/\\/g, "/").toLowerCase();
258+
const normPrefix = worktreePrefix.replace(/\\/g, "/").toLowerCase();
259+
if (normPath.startsWith(normPrefix)) {
260+
return "⌂" + path.slice(normPrefix.length);
258261
}
259262
return path;
260263
}
261264

265+
/** Replace all occurrences of the worktree prefix in arbitrary text (e.g. bash commands). */
262266
function shortenText(text: string, worktreePrefix?: string): string {
263267
if (!worktreePrefix) return text;
264-
return text.split(worktreePrefix).join("⌂");
268+
const normPrefix = worktreePrefix.replace(/\\/g, "/").toLowerCase();
269+
// Walk through text case-insensitively, matching both slash directions
270+
let result = "";
271+
let i = 0;
272+
const normText = text.replace(/\\/g, "/").toLowerCase();
273+
while (i < text.length) {
274+
if (normText.startsWith(normPrefix, i)) {
275+
result += "⌂";
276+
i += normPrefix.length;
277+
} else {
278+
result += text[i];
279+
i++;
280+
}
281+
}
282+
return result;
265283
}
266284

267285
function LogRow({ log, worktreePrefix, toolOutputPreviewLines, showToolOutput = true }: { log: LogEntry; worktreePrefix?: string; toolOutputPreviewLines?: number; showToolOutput?: boolean }) {
@@ -347,30 +365,30 @@ function renderToolHeader(tool: ToolInvocation, color: string, worktreePrefix?:
347365

348366
switch (tool.tool) {
349367
case "Read":
350-
return <div>{badge("Read")}<span style={{ color: "#e2e8f0" }}>{fp(tool.file_path)}</span></div>;
368+
return <div>{badge("Read")}<span style={{ color: "var(--text-primary)" }}>{fp(tool.file_path)}</span></div>;
351369
case "Edit":
352-
return <div>{badge("Edit")}<span style={{ color: "#e2e8f0" }}>{fp(tool.file_path)}</span></div>;
370+
return <div>{badge("Edit")}<span style={{ color: "var(--text-primary)" }}>{fp(tool.file_path)}</span></div>;
353371
case "Write":
354-
return <div>{badge("Write")}<span style={{ color: "#e2e8f0" }}>{fp(tool.file_path)}</span></div>;
372+
return <div>{badge("Write")}<span style={{ color: "var(--text-primary)" }}>{fp(tool.file_path)}</span></div>;
355373
case "Bash":
356374
return (
357375
<div>
358376
{badge("$")}
359-
<span style={{ color: "#e2e8f0" }}>{shortenText(tool.command, worktreePrefix)}</span>
360-
{tool.description && <span style={{ color: "#94a3b8", marginLeft: 8, fontSize: "12px" }}>{tool.description}</span>}
377+
<span style={{ color: "var(--text-primary)" }}>{shortenText(tool.command, worktreePrefix)}</span>
378+
{tool.description && <span style={{ color: "var(--text-muted)", marginLeft: 8, fontSize: "12px" }}>{tool.description}</span>}
361379
</div>
362380
);
363381
case "Glob":
364-
return <div>{badge("Glob")}<span style={{ color: "#e2e8f0" }}>{tool.pattern}</span>{tool.path && <span style={{ color: "#94a3b8" }}> in {fp(tool.path)}</span>}</div>;
382+
return <div>{badge("Glob")}<span style={{ color: "var(--text-primary)" }}>{tool.pattern}</span>{tool.path && <span style={{ color: "var(--text-muted)" }}> in {fp(tool.path)}</span>}</div>;
365383
case "Grep":
366-
return <div>{badge("Grep")}<span style={{ color: "#e2e8f0" }}>{tool.pattern}</span>{tool.path && <span style={{ color: "#94a3b8" }}> in {fp(tool.path)}</span>}</div>;
384+
return <div>{badge("Grep")}<span style={{ color: "var(--text-primary)" }}>{tool.pattern}</span>{tool.path && <span style={{ color: "var(--text-muted)" }}> in {fp(tool.path)}</span>}</div>;
367385
case "Other": {
368386
// Show a compact summary of the input arguments
369387
const summary = Object.entries(tool.input)
370388
.filter(([, v]) => typeof v === "string" || typeof v === "number")
371389
.map(([k, v]) => `${k}: ${String(v).slice(0, 80)}`)
372390
.join(", ");
373-
return <div>{badge(tool.name)}{summary && <span style={{ color: "#94a3b8" }}> {summary}</span>}</div>;
391+
return <div>{badge(tool.name)}{summary && <span style={{ color: "var(--text-muted)" }}> {summary}</span>}</div>;
374392
}
375393
}
376394
}
@@ -380,13 +398,13 @@ function renderToolDetail(tool: ToolInvocation) {
380398
return (
381399
<div style={{ marginTop: 4, fontSize: "12px" }}>
382400
{tool.old_string.split("\n").map((line, i) => (
383-
<div key={`old-${i}`} style={{ backgroundColor: "rgba(239,68,68,0.15)", color: "#fca5a5", whiteSpace: "pre" }}>
384-
<span style={{ userSelect: "none", color: "#ef4444" }}>- </span>{line}
401+
<div key={`old-${i}`} style={{ backgroundColor: "rgba(239,68,68,0.15)", color: "var(--text-primary)", whiteSpace: "pre" }}>
402+
<span style={{ userSelect: "none", color: "var(--accent-red)" }}>- </span>{line}
385403
</div>
386404
))}
387405
{tool.new_string.split("\n").map((line, i) => (
388-
<div key={`new-${i}`} style={{ backgroundColor: "rgba(34,197,94,0.15)", color: "#86efac", whiteSpace: "pre" }}>
389-
<span style={{ userSelect: "none", color: "#22c55e" }}>+ </span>{line}
406+
<div key={`new-${i}`} style={{ backgroundColor: "rgba(34,197,94,0.15)", color: "var(--text-primary)", whiteSpace: "pre" }}>
407+
<span style={{ userSelect: "none", color: "var(--accent-green)" }}>+ </span>{line}
390408
</div>
391409
))}
392410
</div>
@@ -409,7 +427,7 @@ function ToolResultBlock({ content, isError, previewLines = 2 }: { content: stri
409427
<div
410428
style={{
411429
paddingLeft: 10,
412-
color: isError ? "var(--log-error)" : "#94a3b8",
430+
color: isError ? "var(--log-error)" : "var(--text-muted)",
413431
fontSize: "12px",
414432
cursor: isLong ? "pointer" : undefined,
415433
}}
@@ -418,21 +436,21 @@ function ToolResultBlock({ content, isError, previewLines = 2 }: { content: stri
418436
{displayLines.map((line, i) => {
419437
if (isDiff) {
420438
if (line.startsWith("+")) {
421-
return <div key={i} style={{ backgroundColor: "rgba(34,197,94,0.15)", color: "#86efac", whiteSpace: "pre" }}>{line}</div>;
439+
return <div key={i} style={{ backgroundColor: "rgba(34,197,94,0.15)", color: "var(--accent-green)", whiteSpace: "pre" }}>{line}</div>;
422440
}
423441
if (line.startsWith("-")) {
424-
return <div key={i} style={{ backgroundColor: "rgba(239,68,68,0.15)", color: "#fca5a5", whiteSpace: "pre" }}>{line}</div>;
442+
return <div key={i} style={{ backgroundColor: "rgba(239,68,68,0.15)", color: "var(--accent-red)", whiteSpace: "pre" }}>{line}</div>;
425443
}
426444
}
427445
return <div key={i} style={{ whiteSpace: "pre-wrap", wordBreak: "break-all" }}>{line}</div>;
428446
})}
429447
{isLong && !expanded && (
430-
<div style={{ color: "#64748b", fontStyle: "italic" }}>
448+
<div style={{ color: "var(--text-muted)", fontStyle: "italic" }}>
431449
... {lines.length - previewLines} more lines (click to expand)
432450
</div>
433451
)}
434452
{isLong && expanded && (
435-
<div style={{ color: "#64748b", fontStyle: "italic" }}>
453+
<div style={{ color: "var(--text-muted)", fontStyle: "italic" }}>
436454
(click to collapse)
437455
</div>
438456
)}
@@ -452,7 +470,7 @@ function HousekeepingRow({ block }: { block: HousekeepingBlock }) {
452470
);
453471
case "StepCompleted":
454472
return (
455-
<div style={{ color: "#4ade80", display: "flex", alignItems: "center", gap: 6 }}>
473+
<div style={{ color: "var(--accent-green)", display: "flex", alignItems: "center", gap: 6 }}>
456474
<span></span>
457475
<StepBadge step={block.step} />
458476
<span>{block.summary}</span>

src/styles/globals.css

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -31,23 +31,23 @@
3131
}
3232

3333
[data-theme="light"] {
34-
--bg-primary: #f0f1f3;
35-
--bg-secondary: #e4e6ea;
36-
--bg-tertiary: #d4d7dc;
37-
--bg-selected: #c8dff5;
38-
--text-primary: #1f2328;
39-
--text-secondary: #4d566a;
40-
--text-muted: #6e7781;
41-
--border-primary: #bcc3cc;
42-
--border-hover: #a0a8b4;
34+
--bg-primary: #e2e4e8;
35+
--bg-secondary: #d6d9de;
36+
--bg-tertiary: #c8ccd2;
37+
--bg-selected: #b8d4f0;
38+
--text-primary: #1a1e24;
39+
--text-secondary: #3d4555;
40+
--text-muted: #5c6370;
41+
--border-primary: #adb4be;
42+
--border-hover: #939ba8;
4343
--accent-blue: #0969da;
4444
--accent-green: #1a7f37;
4545
--accent-red: #cf222e;
4646
--accent-yellow: #9a6700;
4747
--overlay-bg: rgba(0, 0, 0, 0.3);
48-
--scrollbar-track: #e4e6ea;
49-
--scrollbar-thumb: #bcc3cc;
50-
--scrollbar-thumb-hover: #a0a8b4;
48+
--scrollbar-track: #d6d9de;
49+
--scrollbar-thumb: #adb4be;
50+
--scrollbar-thumb-hover: #939ba8;
5151
--log-git: #0550ae;
5252
--log-ai: #1a7f37;
5353
--log-script: #8250df;
@@ -57,8 +57,8 @@
5757
--status-running: #1a7f37;
5858
--status-stopping: #9a6700;
5959
--status-failed: #cf222e;
60-
--badge-bg: #d4d7dc;
61-
--grid-gap: #bcc3cc;
60+
--badge-bg: #c8ccd2;
61+
--grid-gap: #adb4be;
6262
}
6363

6464
* {

0 commit comments

Comments
 (0)