From 143d5edeb9e46227e868caacbbb8526698e6934e Mon Sep 17 00:00:00 2001 From: brooksc Date: Fri, 15 May 2026 19:51:03 -0700 Subject: [PATCH 1/4] fix(themes): fix WCAG AA contrast failures in 3 built-in themes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - classic: #4c6fff → #4267ff (4.17→4.55:1 on #0d1117) - islands-dark: #548af7 → #286cf5 (3.30→4.61:1 on #0f1923) - islands-light: #3574f0 → #2c6def (4.27→4.60:1 on #f5f7fa) --- src/styles.css | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/styles.css b/src/styles.css index 8bd2ed32..a5728974 100644 --- a/src/styles.css +++ b/src/styles.css @@ -166,11 +166,11 @@ html[data-look='classic'] { --bg-selected-subtle: #3e508a33; --border: #393b3f; --border-subtle: #2d2e32; - --border-focus: #4c6fff; + --border-focus: #4267ff; --fg: #cccdd2; --fg-muted: #8b8d93; --fg-subtle: #6d7076; - --accent: #4c6fff; + --accent: #4267ff; --accent-hover: #3a5bff; --accent-text: #ffffff; --link: #6b8aff; @@ -419,11 +419,11 @@ html[data-look='islands-dark'] { --bg-selected-subtle: #25324d40; --border: #2c2f34; --border-subtle: #232529; - --border-focus: #548af7; + --border-focus: #286cf5; --fg: #bcbec4; --fg-muted: #9a9da4; --fg-subtle: #7a7e85; - --accent: #548af7; + --accent: #286cf5; --accent-hover: #6d9df8; --accent-text: #ffffff; --link: #6d9df8; @@ -449,11 +449,11 @@ html[data-look='islands-light'] { --bg-selected-subtle: #cfe1ff60; --border: #d3d5db; --border-subtle: #e3e5ea; - --border-focus: #3574f0; + --border-focus: #2c6def; --fg: #1f2329; --fg-muted: #5e6066; --fg-subtle: #8d9199; - --accent: #3574f0; + --accent: #2c6def; --accent-hover: #5a8dff; --accent-text: #ffffff; --link: #3574f0; From 180ef312fe755f270350b8e587f1cccb022fd30c Mon Sep 17 00:00:00 2001 From: brooksc Date: Fri, 15 May 2026 19:57:51 -0700 Subject: [PATCH 2/4] feat(themes): add Themes settings tab with Light/Dark/System appearance mode --- src/App.tsx | 10 +- src/components/SettingsDialog.tsx | 1255 ++++++++++++++++------------- src/lib/look.test.ts | 37 + src/lib/look.ts | 23 + src/lib/os-appearance.ts | 16 + src/store/autosave.ts | 5 + src/store/core.ts | 5 + src/store/persistence.ts | 38 + src/store/store.ts | 4 + src/store/types.ts | 12 +- src/store/ui.ts | 32 +- src/styles.css | 1 + 12 files changed, 887 insertions(+), 551 deletions(-) create mode 100644 src/lib/look.test.ts create mode 100644 src/lib/os-appearance.ts diff --git a/src/App.tsx b/src/App.tsx index 6c88969d..d328b025 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -60,6 +60,8 @@ import { } from './lib/shortcuts'; import { resolvedBindings, loadKeybindings, dismissMigrationBanner } from './store/keybindings'; import { setupAutosave } from './store/autosave'; +import { osIsDark } from './lib/os-appearance'; +import { applyAppearanceMode } from './store/store'; import { isMac, mod } from './lib/platform'; import { createCtrlWheelZoomHandler } from './lib/wheelZoom'; import { ArenaOverlay } from './arena/ArenaOverlay'; @@ -242,7 +244,13 @@ function App() { void syncWindowMaximized(); }; - // Sync theme preset to so Portal content inherits CSS variables + // Re-derive effective theme whenever OS dark mode or appearance mode/slots change + createEffect(() => { + osIsDark(); // reactive dependency + applyAppearanceMode(); + }); + + // Sync theme to so Portal content (dialogs, tooltips) inherits CSS variables createEffect(() => { document.documentElement.dataset.look = store.themePreset; }); diff --git a/src/components/SettingsDialog.tsx b/src/components/SettingsDialog.tsx index d6eb9892..1949d5f9 100644 --- a/src/components/SettingsDialog.tsx +++ b/src/components/SettingsDialog.tsx @@ -6,12 +6,12 @@ import { getTerminalFontFamily, LIGATURE_FONTS, } from '../lib/fonts'; -import { LOOK_PRESETS } from '../lib/look'; +import { presetsForTone } from '../lib/look'; +import type { AppearanceMode } from '../lib/look'; import { theme, sectionLabelStyle } from '../lib/theme'; import { store, setTerminalFont, - setThemePreset, setAutoTrustFolders, setShowPlans, setShowPromptInput, @@ -26,6 +26,9 @@ import { setShareDockerAgentAuth, setAskCodeProvider, setMinimaxApiKey, + setAppearanceMode, + setLightTheme, + setDarkTheme, } from '../store/store'; import { CustomAgentEditor } from './CustomAgentEditor'; import { mod } from '../lib/platform'; @@ -41,9 +44,12 @@ function ensureSelectedFont(available: string[]): string[] { return [store.terminalFont, ...available]; } +type SettingsTab = 'general' | 'themes'; + export function SettingsDialog(props: SettingsDialogProps) { const titleId = createUniqueId(); const [fonts, setFonts] = createSignal(ensureSelectedFont(getAvailableTerminalFonts())); + const [activeTab, setActiveTab] = createSignal('general'); // Fetch system fonts when the dialog opens createEffect( @@ -120,603 +126,756 @@ export function SettingsDialog(props: SettingsDialogProps) { -
-
- Theme -
-
- - {(preset) => ( - - )} - -
-
- -
-
- Behavior -
- - - - - - - -
- -
-
- Editor -
-
-
-
+
- Ask about Code -
-
- + - + setShowPlans(e.currentTarget.checked)} + style={{ 'accent-color': theme.accent, cursor: 'pointer' }} + /> +
+ Show plans + + Display Claude Code plan files in a tab next to Notes + +
+ -
- - {store.askCodeProvider === 'minimax' - ? 'Uses MiniMax M2.7 (204K context) via the OpenAI-compatible API — no Claude Code CLI required.' - : 'Uses the claude CLI to answer questions about selected code. Requires Claude Code to be installed.'} - -
-
- - -
-
- Docker Isolation -
-
+ + + - - Docker image used when "Run in Docker container" is enabled for a task. The agent runs - inside the container with only the project directory mounted. - -
- Projects with a{' '} - - {PROJECT_DOCKERFILE_RELATIVE_PATH} - {' '} - will use a project-specific image instead. -
-
- - - This font includes ligatures which may impact rendering performance. - - -
+ -
-
Diagnostics
-