feat: implement light mode with settings toggle

Add appearance theme support (dark/light/system) using CSS custom
property overrides. In light mode the Tailwind zinc scale is inverted
and semantic surface/border tokens are swapped, so all existing
utility classes pick up the new palette automatically.

- Add AppearanceTheme type and theme field to WorkspaceSettings
- Add setTheme IPC channel wiring (contracts, preload, handler, service)
- Add [data-theme='light'] CSS overrides for zinc scale, surface tokens,
  scrollbar, and markdown prose colours
- Add Appearance section to SettingsPanel with radio-button theme picker
- Apply data-theme attribute on document root via useEffect in App.tsx,
  with matchMedia listener for the system option

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
David Kaya
2026-03-24 19:28:48 +01:00
co-authored by Copilot
parent 33c4cee0b4
commit 973e5eb25c
11 changed files with 174 additions and 14 deletions
+11
View File
@@ -40,7 +40,10 @@ export interface WorkspaceToolingSettings {
lspProfiles: LspProfileDefinition[];
}
export type AppearanceTheme = 'dark' | 'light' | 'system';
export interface WorkspaceSettings {
theme: AppearanceTheme;
tooling: WorkspaceToolingSettings;
}
@@ -51,6 +54,7 @@ export interface SessionToolingSelection {
export function createWorkspaceSettings(): WorkspaceSettings {
return {
theme: 'dark',
tooling: {
mcpServers: [],
lspProfiles: [],
@@ -65,8 +69,15 @@ export function createSessionToolingSelection(): SessionToolingSelection {
};
}
const validThemes: ReadonlySet<string> = new Set<AppearanceTheme>(['dark', 'light', 'system']);
export function normalizeTheme(value?: string): AppearanceTheme {
return validThemes.has(value ?? '') ? (value as AppearanceTheme) : 'dark';
}
export function normalizeWorkspaceSettings(settings?: Partial<WorkspaceSettings>): WorkspaceSettings {
return {
theme: normalizeTheme(settings?.theme),
tooling: {
mcpServers: (settings?.tooling?.mcpServers ?? []).map(normalizeMcpServerDefinition),
lspProfiles: (settings?.tooling?.lspProfiles ?? []).map(normalizeLspProfileDefinition),