From e2657b916cafa79d382658a78a01abca3131173c Mon Sep 17 00:00:00 2001 From: Brennan Benson <79079362+brennanb2025@users.noreply.github.com> Date: Mon, 5 Oct 2026 11:52:03 -0700 Subject: [PATCH 01/16] Add chat contrast and terminal interface matching --- src/renderer/src/assets/main.css | 122 +++++++++++++---- .../native-chat/NativeChatResolvedView.tsx | 4 +- .../NativeChatStructuredSession.test.tsx | 26 +++- .../NativeChatStructuredSession.tsx | 4 +- .../native-chat-appearance-style.test.ts | 125 +++++++++++++++++- .../native-chat-appearance-style.ts | 82 ++++++++++-- .../native-chat/native-chat-appearance.css | 12 ++ .../AppearanceChatContrastControls.test.tsx | 43 ++++++ .../AppearanceChatContrastControls.tsx | 70 ++++++++++ .../settings/AppearanceChatSection.test.tsx | 3 + .../settings/AppearanceChatSection.tsx | 6 + .../settings/chat-appearance-search.ts | 23 +++- src/renderer/src/i18n/locales/en.json | 10 +- src/renderer/src/i18n/locales/es.json | 10 +- src/renderer/src/i18n/locales/fr.json | 10 +- src/renderer/src/i18n/locales/ja.json | 10 +- src/renderer/src/i18n/locales/ko.json | 10 +- src/renderer/src/i18n/locales/zh.json | 10 +- .../native-chat-appearance-settings.test.ts | 51 ++++++- src/shared/native-chat-appearance-settings.ts | 18 ++- 20 files changed, 592 insertions(+), 57 deletions(-) create mode 100644 src/renderer/src/components/settings/AppearanceChatContrastControls.test.tsx create mode 100644 src/renderer/src/components/settings/AppearanceChatContrastControls.tsx diff --git a/src/renderer/src/assets/main.css b/src/renderer/src/assets/main.css index aa4c597f108b..b77ab8136ba5 100644 --- a/src/renderer/src/assets/main.css +++ b/src/renderer/src/assets/main.css @@ -43,6 +43,9 @@ @theme inline { --color-background: var(--background); --color-foreground: var(--foreground); + --color-chat-source-background: var(--chat-source-background); + --color-chat-source-foreground: var(--chat-source-foreground); + --color-chat-source-muted-foreground: var(--chat-source-muted-foreground); --color-chat-canvas: var(--chat-canvas); --color-chat-foreground: var(--chat-foreground); --color-chat-foreground-strong: var(--chat-foreground-strong); @@ -173,19 +176,20 @@ --background: #fff; --editor-surface: #ffffff; --foreground: #0a0a0a; - --chat-canvas: var(--background); - --chat-foreground: color-mix(in srgb, var(--foreground) 82%, var(--chat-canvas)); - --chat-foreground-strong: color-mix(in srgb, var(--foreground) 92%, var(--chat-canvas)); - --chat-foreground-faint: var(--muted-foreground); - --chat-user-surface: color-mix(in srgb, var(--foreground) 4%, var(--chat-canvas)); - --chat-user-border: color-mix(in srgb, var(--foreground) 7%, transparent); - --chat-code-foreground: color-mix(in srgb, var(--foreground) 85%, var(--chat-canvas)); - --chat-code-surface: color-mix(in srgb, var(--foreground) 2%, var(--chat-canvas)); - --chat-code-border: color-mix(in srgb, var(--foreground) 7%, transparent); - --chat-inline-code-surface: color-mix(in srgb, var(--foreground) 4%, var(--chat-canvas)); - --chat-inline-code-border: color-mix(in srgb, var(--foreground) 9%, transparent); - --chat-composer-surface: var(--chat-canvas); - --chat-composer-border: color-mix(in srgb, var(--foreground) 11%, transparent); + --chat-canvas-mix: 0%; + --chat-foreground-mix: 82%; + --chat-strong-mix: 92%; + --chat-faint-mix: 100%; + --chat-user-mix: 4%; + --chat-user-border-mix: 7%; + --chat-code-mix: 2%; + --chat-code-base: var(--chat-canvas); + --chat-inline-code-mix: 4%; + --chat-inline-code-base: var(--chat-canvas); + --chat-inline-code-border-mix: 9%; + --chat-composer-mix: 0%; + --chat-composer-base: var(--chat-canvas); + --chat-composer-border-mix: 11%; --chat-content-max-width: 46rem; --card: #fff; --card-foreground: #0a0a0a; @@ -310,19 +314,20 @@ --background: #0a0a0a; --editor-surface: #1e1e1e; --foreground: #fafafa; - --chat-canvas: color-mix(in srgb, var(--foreground) 5%, var(--background)); - --chat-foreground: color-mix(in srgb, var(--foreground) 78%, var(--chat-canvas)); - --chat-foreground-strong: color-mix(in srgb, var(--foreground) 90%, var(--chat-canvas)); - --chat-foreground-faint: color-mix(in srgb, var(--muted-foreground) 83%, var(--chat-canvas)); - --chat-user-surface: color-mix(in srgb, var(--foreground) 7%, var(--chat-canvas)); - --chat-user-border: color-mix(in srgb, var(--foreground) 6%, transparent); - --chat-code-foreground: color-mix(in srgb, var(--foreground) 85%, var(--chat-canvas)); - --chat-code-surface: color-mix(in srgb, var(--foreground) 3.5%, transparent); - --chat-code-border: color-mix(in srgb, var(--foreground) 7%, transparent); - --chat-inline-code-surface: color-mix(in srgb, var(--foreground) 6%, transparent); - --chat-inline-code-border: color-mix(in srgb, var(--foreground) 8%, transparent); - --chat-composer-surface: color-mix(in srgb, var(--foreground) 4%, transparent); - --chat-composer-border: color-mix(in srgb, var(--foreground) 9%, transparent); + --chat-canvas-mix: 5%; + --chat-foreground-mix: 78%; + --chat-strong-mix: 90%; + --chat-faint-mix: 83%; + --chat-user-mix: 7%; + --chat-user-border-mix: 6%; + --chat-code-mix: 3.5%; + --chat-code-base: transparent; + --chat-inline-code-mix: 6%; + --chat-inline-code-base: transparent; + --chat-inline-code-border-mix: 8%; + --chat-composer-mix: 4%; + --chat-composer-base: transparent; + --chat-composer-border-mix: 9%; --chat-content-max-width: 46rem; --card: #171717; --card-foreground: #fafafa; @@ -529,6 +534,71 @@ body:has(> [data-slot='dialog-overlay'], > [data-slot='sheet-overlay']) { /* ── Base Layer ──────────────────────────────────────── */ +/* Re-evaluate chat colors where the appearance producer supplies their source colors. */ +:root, +.dark, +.native-chat-appearance { + --chat-source-background: var(--background); + --chat-source-foreground: var(--foreground); + --chat-source-muted-foreground: var(--muted-foreground); + --chat-canvas: color-mix( + in srgb, + var(--chat-source-foreground) var(--chat-canvas-mix), + var(--chat-source-background) + ); + --chat-foreground: color-mix( + in srgb, + var(--chat-source-foreground) var(--chat-foreground-mix), + var(--chat-canvas) + ); + --chat-foreground-strong: color-mix( + in srgb, + var(--chat-source-foreground) var(--chat-strong-mix), + var(--chat-canvas) + ); + --chat-foreground-faint: color-mix( + in srgb, + var(--chat-source-muted-foreground) var(--chat-faint-mix), + var(--chat-canvas) + ); + --chat-user-surface: color-mix( + in srgb, + var(--chat-source-foreground) var(--chat-user-mix), + var(--chat-canvas) + ); + --chat-user-border: color-mix( + in srgb, + var(--chat-source-foreground) var(--chat-user-border-mix), + transparent + ); + --chat-code-surface: color-mix( + in srgb, + var(--chat-source-foreground) var(--chat-code-mix), + var(--chat-code-base) + ); + --chat-code-border: color-mix(in srgb, var(--chat-source-foreground) 7%, transparent); + --chat-inline-code-surface: color-mix( + in srgb, + var(--chat-source-foreground) var(--chat-inline-code-mix), + var(--chat-inline-code-base) + ); + --chat-inline-code-border: color-mix( + in srgb, + var(--chat-source-foreground) var(--chat-inline-code-border-mix), + transparent + ); + --chat-composer-surface: color-mix( + in srgb, + var(--chat-source-foreground) var(--chat-composer-mix), + var(--chat-composer-base) + ); + --chat-composer-border: color-mix( + in srgb, + var(--chat-source-foreground) var(--chat-composer-border-mix), + transparent + ); +} + @layer base { *, *::before, diff --git a/src/renderer/src/components/native-chat/NativeChatResolvedView.tsx b/src/renderer/src/components/native-chat/NativeChatResolvedView.tsx index 9d48e563a80a..a3094ddf36ee 100644 --- a/src/renderer/src/components/native-chat/NativeChatResolvedView.tsx +++ b/src/renderer/src/components/native-chat/NativeChatResolvedView.tsx @@ -315,8 +315,8 @@ export function NativeChatResolvedView({ // Only the focused conversation accepts chat text-size shortcuts. useNativeChatFontSize(isConversation && isVisible && isFocusedGroup, rootRef) - const appearanceSettings = useAppStore((state) => state.settings?.nativeChatAppearance) - const appearanceStyle = useNativeChatAppearanceStyle({ nativeChatAppearance: appearanceSettings }) + const appearanceSettings = useAppStore((state) => state.settings) + const appearanceStyle = useNativeChatAppearanceStyle(appearanceSettings) return (