feat(ui): terminal, charts and low-contrast text follow the selected theme

- The lane terminal (xterm) takes its palette from the selected DARK theme —
  it stays dark in light mode, as a terminal should — and repaints live when
  the theme changes (`client/src/lib/terminalTheme.ts`).
- Charts on the Dashboard and Workflows pages draw their grid, axes, labels
  and tooltips from theme tokens instead of hardcoded near-black/white, and
  the activity heatmap ramps from the page surface to the accent, so it reads
  on every theme instead of going near-black on light ones.
- Status/brand text that only worked on dark backgrounds
  (`text-*-300/400`) gets a darker light-mode shade (`text-*-700
  dark:text-*-300`) across sessions, conversations, workflows, config and
  settings. Categorical chart colours are kept.
This commit is contained in:
2026-09-24 09:50:44 +07:00
parent 6353e88c9e
commit 8ea40260ad
36 changed files with 919 additions and 635 deletions
@@ -75,7 +75,7 @@ type AgentNode = SessionDrillInData["tree"][number];
function statusColor(status: string): string {
switch (status) {
case "completed":
return "text-violet-400 bg-violet-500/10 border-violet-500/20";
return "text-violet-700 dark:text-violet-400 bg-violet-500/10 border-violet-500/20";
case "working":
return "text-status-success bg-status-success/10 border-status-success/20";
case "error":
@@ -83,7 +83,7 @@ function statusColor(status: string): string {
case "active":
return "text-status-success bg-status-success/10 border-status-success/20";
case "waiting":
return "text-yellow-400 bg-yellow-500/10 border-yellow-500/20";
return "text-yellow-700 dark:text-yellow-400 bg-yellow-500/10 border-yellow-500/20";
default:
return "text-fg-secondary bg-surface-4/10 border-border-light/20";
}
@@ -186,7 +186,7 @@ function TreeNode({ node, depth }: TreeNodeProps) {
{/* Name */}
<span
className={`text-sm font-medium truncate ${isMain ? "text-indigo-300" : "text-fg-secondary"}`}
className={`text-sm font-medium truncate ${isMain ? "text-indigo-700 dark:text-indigo-300" : "text-fg-secondary"}`}
>
{node.name}
</span>
@@ -255,7 +255,7 @@ function ToolTimeline({ events }: ToolTimelineProps) {
className="flex items-center gap-2 px-2 py-1.5 rounded hover:bg-surface-4 transition-colors"
>
{/* Tool pill */}
<span className="flex-shrink-0 inline-flex items-center px-2 py-0.5 rounded-md text-xs font-medium bg-indigo-500/15 text-indigo-300 border border-indigo-500/20 whitespace-nowrap">
<span className="flex-shrink-0 inline-flex items-center px-2 py-0.5 rounded-md text-xs font-medium bg-indigo-500/15 text-indigo-700 dark:text-indigo-300 border border-indigo-500/20 whitespace-nowrap">
{ev.tool_name ?? ev.event_type}
</span>
@@ -286,8 +286,8 @@ interface EventSequenceProps {
const EVENT_TYPE_COLOR: Record<string, string> = {
tool_use: "text-blue-500",
tool_result: "text-status-success",
agent_start: "text-indigo-400",
agent_stop: "text-violet-400",
agent_start: "text-indigo-700 dark:text-indigo-400",
agent_stop: "text-violet-700 dark:text-violet-400",
compaction: "text-status-warning",
error: "text-status-danger",
};