{filename}
diff --git a/src/renderer/components/WorktreeConfigModal.tsx b/src/renderer/components/WorktreeConfigModal.tsx
index 033d05ad0..2da98323d 100644
--- a/src/renderer/components/WorktreeConfigModal.tsx
+++ b/src/renderer/components/WorktreeConfigModal.tsx
@@ -179,7 +179,7 @@ export function WorktreeConfigModal({
return (
{/* Backdrop */}
-
+
{/* Modal */}
= {
fuzzyFileSearch: { id: 'fuzzyFileSearch', label: 'Fuzzy File Search', keys: ['Meta', 'g'] },
toggleBookmark: { id: 'toggleBookmark', label: 'Toggle Bookmark', keys: ['Meta', 'Shift', 'b'] },
openSymphony: { id: 'openSymphony', label: 'Maestro Symphony', keys: ['Meta', 'Shift', 'y'] },
+ toggleAutoScroll: {
+ id: 'toggleAutoScroll',
+ label: 'Toggle Auto-Scroll AI Output',
+ keys: ['Alt', 'Meta', 's'],
+ },
directorNotes: {
id: 'directorNotes',
label: "Director's Notes",
diff --git a/src/renderer/hooks/keyboard/useMainKeyboardHandler.ts b/src/renderer/hooks/keyboard/useMainKeyboardHandler.ts
index f35def81a..d12454737 100644
--- a/src/renderer/hooks/keyboard/useMainKeyboardHandler.ts
+++ b/src/renderer/hooks/keyboard/useMainKeyboardHandler.ts
@@ -104,13 +104,13 @@ export function useMainKeyboardHandler(): UseMainKeyboardHandlerReturn {
// (e.g., when output search is open, user should still be able to toggle markdown mode)
const isMarkdownToggleShortcut =
(e.metaKey || e.ctrlKey) && !e.shiftKey && !e.altKey && keyLower === 'e';
- // Allow system utility shortcuts (Alt+Cmd+L for logs, Alt+Cmd+P for processes) even when modals are open
+ // Allow system utility shortcuts (Alt+Cmd+L for logs, Alt+Cmd+P for processes, Alt+Cmd+S for auto-scroll toggle) even when modals are open
// NOTE: Must use e.code for Alt key combos on macOS because e.key produces special characters (e.g., Alt+P = π)
const codeKeyLower = e.code?.replace('Key', '').toLowerCase() || '';
const isSystemUtilShortcut =
e.altKey &&
(e.metaKey || e.ctrlKey) &&
- (codeKeyLower === 'l' || codeKeyLower === 'p' || codeKeyLower === 'u');
+ (codeKeyLower === 'l' || codeKeyLower === 'p' || codeKeyLower === 'u' || codeKeyLower === 's');
// Allow session jump shortcuts (Alt+Cmd+NUMBER) even when modals are open
// NOTE: Must use e.code for Alt key combos on macOS because e.key produces special characters
const isSessionJumpShortcut =
@@ -404,6 +404,10 @@ export function useMainKeyboardHandler(): UseMainKeyboardHandlerReturn {
e.preventDefault();
ctx.setSymphonyModalOpen(true);
trackShortcut('openSymphony');
+ } else if (ctx.isShortcut(e, 'toggleAutoScroll')) {
+ e.preventDefault();
+ ctx.setAutoScrollAiMode(!ctx.autoScrollAiMode);
+ trackShortcut('toggleAutoScroll');
} else if (ctx.isShortcut(e, 'directorNotes')) {
e.preventDefault();
ctx.setDirectorNotesOpen(true);
diff --git a/src/renderer/hooks/props/useMainPanelProps.ts b/src/renderer/hooks/props/useMainPanelProps.ts
index 06aed0a49..7d259942f 100644
--- a/src/renderer/hooks/props/useMainPanelProps.ts
+++ b/src/renderer/hooks/props/useMainPanelProps.ts
@@ -63,6 +63,8 @@ export interface UseMainPanelPropsDeps {
filePreviewLoading: { name: string; path: string } | null;
markdownEditMode: boolean; // FilePreview: whether editing file content
chatRawTextMode: boolean; // TerminalOutput: whether to show raw text in AI responses
+ autoScrollAiMode: boolean; // Whether to auto-scroll in AI mode
+ setAutoScrollAiMode: (value: boolean) => void; // Toggle auto-scroll in AI mode
shortcuts: Record;
rightPanelOpen: boolean;
maxOutputLines: number;
@@ -334,6 +336,8 @@ export function useMainPanelProps(deps: UseMainPanelPropsDeps) {
filePreviewLoading: deps.filePreviewLoading,
markdownEditMode: deps.markdownEditMode,
chatRawTextMode: deps.chatRawTextMode,
+ autoScrollAiMode: deps.autoScrollAiMode,
+ setAutoScrollAiMode: deps.setAutoScrollAiMode,
shortcuts: deps.shortcuts,
rightPanelOpen: deps.rightPanelOpen,
maxOutputLines: deps.maxOutputLines,
@@ -555,6 +559,8 @@ export function useMainPanelProps(deps: UseMainPanelPropsDeps) {
deps.filePreviewLoading,
deps.markdownEditMode,
deps.chatRawTextMode,
+ deps.autoScrollAiMode,
+ deps.setAutoScrollAiMode,
deps.shortcuts,
deps.rightPanelOpen,
deps.maxOutputLines,
diff --git a/src/renderer/hooks/settings/useSettings.ts b/src/renderer/hooks/settings/useSettings.ts
index 259d39add..e60e643b6 100644
--- a/src/renderer/hooks/settings/useSettings.ts
+++ b/src/renderer/hooks/settings/useSettings.ts
@@ -26,6 +26,7 @@ import type {
KeyboardMasteryStats,
ThinkingMode,
DirectorNotesSettings,
+ EncoreFeatureFlags,
} from '../../types';
import {
useSettingsStore,
@@ -270,6 +271,18 @@ export interface UseSettingsReturn {
suppressWindowsWarning: boolean;
setSuppressWindowsWarning: (value: boolean) => void;
+ // Auto-scroll in AI mode
+ autoScrollAiMode: boolean;
+ setAutoScrollAiMode: (value: boolean) => void;
+
+ // Message alignment
+ userMessageAlignment: 'left' | 'right';
+ setUserMessageAlignment: (value: 'left' | 'right') => void;
+
+ // Encore Features - optional features disabled by default
+ encoreFeatures: EncoreFeatureFlags;
+ setEncoreFeatures: (value: EncoreFeatureFlags) => void;
+
// Director's Notes settings
directorNotesSettings: DirectorNotesSettings;
setDirectorNotesSettings: (value: DirectorNotesSettings) => void;
@@ -279,6 +292,12 @@ export interface UseSettingsReturn {
setWakatimeApiKey: (value: string) => void;
wakatimeEnabled: boolean;
setWakatimeEnabled: (value: boolean) => void;
+
+ // Window chrome settings
+ useNativeTitleBar: boolean;
+ setUseNativeTitleBar: (value: boolean) => void;
+ autoHideMenuBar: boolean;
+ setAutoHideMenuBar: (value: boolean) => void;
}
export function useSettings(): UseSettingsReturn {
diff --git a/src/renderer/stores/settingsStore.ts b/src/renderer/stores/settingsStore.ts
index f9f4308da..dd784e3d1 100644
--- a/src/renderer/stores/settingsStore.ts
+++ b/src/renderer/stores/settingsStore.ts
@@ -30,6 +30,7 @@ import type {
KeyboardMasteryStats,
ThinkingMode,
DirectorNotesSettings,
+ EncoreFeatureFlags,
} from '../types';
import { DEFAULT_CUSTOM_THEME_COLORS } from '../constants/themes';
import { DEFAULT_SHORTCUTS, TAB_SHORTCUTS, FIXED_SHORTCUTS } from '../constants/shortcuts';
@@ -115,6 +116,10 @@ export const DEFAULT_ONBOARDING_STATS: OnboardingStats = {
averageTasksPerPhase: 0,
};
+export const DEFAULT_ENCORE_FEATURES: EncoreFeatureFlags = {
+ directorNotes: false,
+};
+
export const DEFAULT_DIRECTOR_NOTES_SETTINGS: DirectorNotesSettings = {
provider: 'claude-code',
defaultLookbackDays: 7,
@@ -236,9 +241,14 @@ export interface SettingsStoreState {
automaticTabNamingEnabled: boolean;
fileTabAutoRefreshEnabled: boolean;
suppressWindowsWarning: boolean;
+ autoScrollAiMode: boolean;
+ userMessageAlignment: 'left' | 'right';
+ encoreFeatures: EncoreFeatureFlags;
directorNotesSettings: DirectorNotesSettings;
wakatimeApiKey: string;
wakatimeEnabled: boolean;
+ useNativeTitleBar: boolean;
+ autoHideMenuBar: boolean;
}
export interface SettingsStoreActions {
@@ -298,9 +308,14 @@ export interface SettingsStoreActions {
setAutomaticTabNamingEnabled: (value: boolean) => void;
setFileTabAutoRefreshEnabled: (value: boolean) => void;
setSuppressWindowsWarning: (value: boolean) => void;
+ setAutoScrollAiMode: (value: boolean) => void;
+ setUserMessageAlignment: (value: 'left' | 'right') => void;
+ setEncoreFeatures: (value: EncoreFeatureFlags) => void;
setDirectorNotesSettings: (value: DirectorNotesSettings) => void;
setWakatimeApiKey: (value: string) => void;
setWakatimeEnabled: (value: boolean) => void;
+ setUseNativeTitleBar: (value: boolean) => void;
+ setAutoHideMenuBar: (value: boolean) => void;
// Async setters
setLogLevel: (value: string) => Promise;
@@ -436,9 +451,14 @@ export const useSettingsStore = create()((set, get) => ({
automaticTabNamingEnabled: true,
fileTabAutoRefreshEnabled: false,
suppressWindowsWarning: false,
+ autoScrollAiMode: false,
+ userMessageAlignment: 'right',
+ encoreFeatures: DEFAULT_ENCORE_FEATURES,
directorNotesSettings: DEFAULT_DIRECTOR_NOTES_SETTINGS,
wakatimeApiKey: '',
wakatimeEnabled: false,
+ useNativeTitleBar: false,
+ autoHideMenuBar: false,
// ============================================================================
// Simple Setters
@@ -727,6 +747,21 @@ export const useSettingsStore = create()((set, get) => ({
window.maestro.settings.set('suppressWindowsWarning', value);
},
+ setAutoScrollAiMode: (value) => {
+ set({ autoScrollAiMode: value });
+ window.maestro.settings.set('autoScrollAiMode', value);
+ },
+
+ setUserMessageAlignment: (value) => {
+ set({ userMessageAlignment: value });
+ window.maestro.settings.set('userMessageAlignment', value);
+ },
+
+ setEncoreFeatures: (value) => {
+ set({ encoreFeatures: value });
+ window.maestro.settings.set('encoreFeatures', value);
+ },
+
setDirectorNotesSettings: (value) => {
set({ directorNotesSettings: value });
window.maestro.settings.set('directorNotesSettings', value);
@@ -742,6 +777,16 @@ export const useSettingsStore = create()((set, get) => ({
window.maestro.settings.set('wakatimeEnabled', value);
},
+ setUseNativeTitleBar: (value) => {
+ set({ useNativeTitleBar: value });
+ window.maestro.settings.set('useNativeTitleBar', value);
+ },
+
+ setAutoHideMenuBar: (value) => {
+ set({ autoHideMenuBar: value });
+ window.maestro.settings.set('autoHideMenuBar', value);
+ },
+
// ============================================================================
// Async Setters
// ============================================================================
@@ -1292,8 +1337,13 @@ export async function loadAllSettings(): Promise {
if (allSettings['activeThemeId'] !== undefined)
patch.activeThemeId = allSettings['activeThemeId'] as ThemeId;
+ // Custom theme migration: merge saved tokens with defaults so themes
+ // created with 13 tokens gain the 17 new tokens added in the WCAG update.
if (allSettings['customThemeColors'] !== undefined)
- patch.customThemeColors = allSettings['customThemeColors'] as ThemeColors;
+ patch.customThemeColors = {
+ ...DEFAULT_CUSTOM_THEME_COLORS,
+ ...(allSettings['customThemeColors'] as ThemeColors),
+ };
if (allSettings['customThemeBaseId'] !== undefined)
patch.customThemeBaseId = allSettings['customThemeBaseId'] as ThemeId;
@@ -1591,6 +1641,20 @@ export async function loadAllSettings(): Promise {
if (allSettings['suppressWindowsWarning'] !== undefined)
patch.suppressWindowsWarning = allSettings['suppressWindowsWarning'] as boolean;
+ if (allSettings['autoScrollAiMode'] !== undefined)
+ patch.autoScrollAiMode = allSettings['autoScrollAiMode'] as boolean;
+
+ if (allSettings['userMessageAlignment'] !== undefined)
+ patch.userMessageAlignment = allSettings['userMessageAlignment'] as 'left' | 'right';
+
+ // Encore Features (merge with defaults to preserve new flags)
+ if (allSettings['encoreFeatures'] !== undefined) {
+ patch.encoreFeatures = {
+ ...DEFAULT_ENCORE_FEATURES,
+ ...(allSettings['encoreFeatures'] as Partial),
+ };
+ }
+
// Director's Notes settings (merge with defaults to preserve new fields)
if (allSettings['directorNotesSettings'] !== undefined) {
patch.directorNotesSettings = {
@@ -1605,6 +1669,12 @@ export async function loadAllSettings(): Promise {
if (allSettings['wakatimeEnabled'] !== undefined)
patch.wakatimeEnabled = allSettings['wakatimeEnabled'] as boolean;
+ if (allSettings['useNativeTitleBar'] !== undefined)
+ patch.useNativeTitleBar = allSettings['useNativeTitleBar'] as boolean;
+
+ if (allSettings['autoHideMenuBar'] !== undefined)
+ patch.autoHideMenuBar = allSettings['autoHideMenuBar'] as boolean;
+
// Apply the entire patch in one setState call
patch.settingsLoaded = true;
useSettingsStore.setState(patch);
@@ -1708,8 +1778,12 @@ export function getSettingsActions() {
setAutomaticTabNamingEnabled: state.setAutomaticTabNamingEnabled,
setFileTabAutoRefreshEnabled: state.setFileTabAutoRefreshEnabled,
setSuppressWindowsWarning: state.setSuppressWindowsWarning,
+ setAutoScrollAiMode: state.setAutoScrollAiMode,
+ setEncoreFeatures: state.setEncoreFeatures,
setDirectorNotesSettings: state.setDirectorNotesSettings,
setWakatimeApiKey: state.setWakatimeApiKey,
setWakatimeEnabled: state.setWakatimeEnabled,
+ setUseNativeTitleBar: state.setUseNativeTitleBar,
+ setAutoHideMenuBar: state.setAutoHideMenuBar,
};
}
diff --git a/src/renderer/types/index.ts b/src/renderer/types/index.ts
index 217ace0d1..a195552b0 100644
--- a/src/renderer/types/index.ts
+++ b/src/renderer/types/index.ts
@@ -901,6 +901,12 @@ export interface LeaderboardSubmitResponse {
};
}
+// Encore Features - optional features that are disabled by default
+// Each key is a feature ID, value indicates whether it's enabled
+export interface EncoreFeatureFlags {
+ directorNotes: boolean;
+}
+
// Director's Notes settings for synopsis generation
export interface DirectorNotesSettings {
/** Agent type to use for synopsis generation */
diff --git a/src/renderer/utils/markdownConfig.ts b/src/renderer/utils/markdownConfig.ts
index 329c1627c..36632f41b 100644
--- a/src/renderer/utils/markdownConfig.ts
+++ b/src/renderer/utils/markdownConfig.ts
@@ -541,24 +541,24 @@ export function generateDiffViewStyles(theme: Theme): string {
color: ${c.textMain} !important;
}
.diff-gutter-insert {
- background-color: rgba(34, 197, 94, 0.1) !important;
+ background-color: ${c.diffAdditionBg} !important;
}
.diff-code-insert {
- background-color: rgba(34, 197, 94, 0.15) !important;
+ background-color: ${c.diffAdditionBg} !important;
color: ${c.textMain} !important;
}
.diff-gutter-delete {
- background-color: rgba(239, 68, 68, 0.1) !important;
+ background-color: ${c.diffDeletionBg} !important;
}
.diff-code-delete {
- background-color: rgba(239, 68, 68, 0.15) !important;
+ background-color: ${c.diffDeletionBg} !important;
color: ${c.textMain} !important;
}
.diff-code-insert .diff-code-edit {
- background-color: rgba(34, 197, 94, 0.3) !important;
+ background-color: ${c.diffAddition}40 !important;
}
.diff-code-delete .diff-code-edit {
- background-color: rgba(239, 68, 68, 0.3) !important;
+ background-color: ${c.diffDeletion}40 !important;
}
.diff-hunk-header {
background-color: ${c.bgActivity} !important;
diff --git a/src/shared/theme-types.ts b/src/shared/theme-types.ts
index 027e09e48..44bc86b62 100644
--- a/src/shared/theme-types.ts
+++ b/src/shared/theme-types.ts
@@ -41,6 +41,7 @@ export type ThemeMode = 'light' | 'dark' | 'vibe';
* Each color serves a specific purpose in the UI
*/
export interface ThemeColors {
+ // --- Core backgrounds ---
/** Main background color for primary content areas */
bgMain: string;
/** Sidebar background color */
@@ -49,10 +50,14 @@ export interface ThemeColors {
bgActivity: string;
/** Border color for dividers and outlines */
border: string;
+
+ // --- Typography ---
/** Primary text color */
textMain: string;
/** Dimmed/secondary text color */
textDim: string;
+
+ // --- Accent ---
/** Accent color for highlights and interactive elements */
accent: string;
/** Dimmed accent (typically with alpha transparency) */
@@ -61,12 +66,56 @@ export interface ThemeColors {
accentText: string;
/** Text color for use ON accent backgrounds (contrasting color) */
accentForeground: string;
+
+ // --- Status colors ---
/** Success state color (green tones) */
success: string;
/** Warning state color (yellow/orange tones) */
warning: string;
/** Error state color (red tones) */
error: string;
+ /** Info state color (blue tones) */
+ info: string;
+
+ // --- Status foregrounds (text ON status backgrounds) ---
+ /** Text color for use ON success backgrounds */
+ successForeground: string;
+ /** Text color for use ON warning backgrounds */
+ warningForeground: string;
+ /** Text color for use ON error backgrounds */
+ errorForeground: string;
+
+ // --- Status dim backgrounds (subtle badges/tags) ---
+ /** Dimmed success background for badges and tags */
+ successDim: string;
+ /** Dimmed warning background for badges and tags */
+ warningDim: string;
+ /** Dimmed error background for badges and tags */
+ errorDim: string;
+ /** Dimmed info background for badges and tags */
+ infoDim: string;
+
+ // --- Git diff colors ---
+ /** Color for added lines/files in diffs */
+ diffAddition: string;
+ /** Background for added lines/files in diffs */
+ diffAdditionBg: string;
+ /** Color for deleted lines/files in diffs */
+ diffDeletion: string;
+ /** Background for deleted lines/files in diffs */
+ diffDeletionBg: string;
+
+ // --- Overlay and interactive states ---
+ /** Modal/overlay backdrop color */
+ overlay: string;
+ /** Heavy overlay for wizard/fullscreen modals */
+ overlayHeavy: string;
+ /** Subtle hover state background */
+ hoverBg: string;
+ /** Selected/active state background */
+ activeBg: string;
+ /** Standard elevation shadow color */
+ shadow: string;
}
/**
diff --git a/src/shared/themes.ts b/src/shared/themes.ts
index 8bd1455a0..853710cde 100644
--- a/src/shared/themes.ts
+++ b/src/shared/themes.ts
@@ -32,6 +32,23 @@ export const THEMES: Record = {
success: '#50fa7b',
warning: '#ffb86c',
error: '#ff5555',
+ info: '#8be9fd',
+ successForeground: '#282a36',
+ warningForeground: '#282a36',
+ errorForeground: '#282a36',
+ successDim: 'rgba(80, 250, 123, 0.15)',
+ warningDim: 'rgba(255, 184, 108, 0.15)',
+ errorDim: 'rgba(255, 85, 85, 0.15)',
+ infoDim: 'rgba(139, 233, 253, 0.15)',
+ diffAddition: '#50fa7b',
+ diffAdditionBg: 'rgba(80, 250, 123, 0.15)',
+ diffDeletion: '#ff5555',
+ diffDeletionBg: 'rgba(255, 85, 85, 0.15)',
+ overlay: 'rgba(0, 0, 0, 0.6)',
+ overlayHeavy: 'rgba(0, 0, 0, 0.8)',
+ hoverBg: 'rgba(255, 255, 255, 0.06)',
+ activeBg: 'rgba(255, 255, 255, 0.15)',
+ shadow: 'rgba(0, 0, 0, 0.3)',
},
},
monokai: {
@@ -52,6 +69,23 @@ export const THEMES: Record = {
success: '#a6e22e',
warning: '#e6db74',
error: '#f92672',
+ info: '#66d9ef',
+ successForeground: '#272822',
+ warningForeground: '#272822',
+ errorForeground: '#272822',
+ successDim: 'rgba(166, 226, 46, 0.15)',
+ warningDim: 'rgba(230, 219, 116, 0.15)',
+ errorDim: 'rgba(249, 38, 114, 0.15)',
+ infoDim: 'rgba(102, 217, 239, 0.15)',
+ diffAddition: '#a6e22e',
+ diffAdditionBg: 'rgba(166, 226, 46, 0.15)',
+ diffDeletion: '#f92672',
+ diffDeletionBg: 'rgba(249, 38, 114, 0.15)',
+ overlay: 'rgba(0, 0, 0, 0.6)',
+ overlayHeavy: 'rgba(0, 0, 0, 0.8)',
+ hoverBg: 'rgba(255, 255, 255, 0.06)',
+ activeBg: 'rgba(255, 255, 255, 0.15)',
+ shadow: 'rgba(0, 0, 0, 0.3)',
},
},
nord: {
@@ -72,6 +106,23 @@ export const THEMES: Record = {
success: '#a3be8c',
warning: '#ebcb8b',
error: '#bf616a',
+ info: '#81a1c1',
+ successForeground: '#2e3440',
+ warningForeground: '#2e3440',
+ errorForeground: '#2e3440',
+ successDim: 'rgba(163, 190, 140, 0.15)',
+ warningDim: 'rgba(235, 203, 139, 0.15)',
+ errorDim: 'rgba(191, 97, 106, 0.15)',
+ infoDim: 'rgba(129, 161, 193, 0.15)',
+ diffAddition: '#a3be8c',
+ diffAdditionBg: 'rgba(163, 190, 140, 0.15)',
+ diffDeletion: '#bf616a',
+ diffDeletionBg: 'rgba(191, 97, 106, 0.15)',
+ overlay: 'rgba(0, 0, 0, 0.6)',
+ overlayHeavy: 'rgba(0, 0, 0, 0.8)',
+ hoverBg: 'rgba(255, 255, 255, 0.06)',
+ activeBg: 'rgba(255, 255, 255, 0.15)',
+ shadow: 'rgba(0, 0, 0, 0.3)',
},
},
'tokyo-night': {
@@ -92,6 +143,23 @@ export const THEMES: Record = {
success: '#9ece6a',
warning: '#e0af68',
error: '#f7768e',
+ info: '#7dcfff',
+ successForeground: '#1a1b26',
+ warningForeground: '#1a1b26',
+ errorForeground: '#1a1b26',
+ successDim: 'rgba(158, 206, 106, 0.15)',
+ warningDim: 'rgba(224, 175, 104, 0.15)',
+ errorDim: 'rgba(247, 118, 142, 0.15)',
+ infoDim: 'rgba(125, 207, 255, 0.15)',
+ diffAddition: '#9ece6a',
+ diffAdditionBg: 'rgba(158, 206, 106, 0.15)',
+ diffDeletion: '#f7768e',
+ diffDeletionBg: 'rgba(247, 118, 142, 0.15)',
+ overlay: 'rgba(0, 0, 0, 0.6)',
+ overlayHeavy: 'rgba(0, 0, 0, 0.8)',
+ hoverBg: 'rgba(255, 255, 255, 0.06)',
+ activeBg: 'rgba(255, 255, 255, 0.15)',
+ shadow: 'rgba(0, 0, 0, 0.3)',
},
},
'catppuccin-mocha': {
@@ -112,6 +180,23 @@ export const THEMES: Record = {
success: '#a6e3a1',
warning: '#fab387',
error: '#f38ba8',
+ info: '#89b4fa',
+ successForeground: '#1e1e2e',
+ warningForeground: '#1e1e2e',
+ errorForeground: '#1e1e2e',
+ successDim: 'rgba(166, 227, 161, 0.15)',
+ warningDim: 'rgba(250, 179, 135, 0.15)',
+ errorDim: 'rgba(243, 139, 168, 0.15)',
+ infoDim: 'rgba(137, 180, 250, 0.15)',
+ diffAddition: '#a6e3a1',
+ diffAdditionBg: 'rgba(166, 227, 161, 0.15)',
+ diffDeletion: '#f38ba8',
+ diffDeletionBg: 'rgba(243, 139, 168, 0.15)',
+ overlay: 'rgba(0, 0, 0, 0.6)',
+ overlayHeavy: 'rgba(0, 0, 0, 0.8)',
+ hoverBg: 'rgba(255, 255, 255, 0.06)',
+ activeBg: 'rgba(255, 255, 255, 0.15)',
+ shadow: 'rgba(0, 0, 0, 0.3)',
},
},
'gruvbox-dark': {
@@ -132,6 +217,23 @@ export const THEMES: Record = {
success: '#b8bb26',
warning: '#fabd2f',
error: '#fb4934',
+ info: '#83a598',
+ successForeground: '#282828',
+ warningForeground: '#282828',
+ errorForeground: '#282828',
+ successDim: 'rgba(184, 187, 38, 0.15)',
+ warningDim: 'rgba(250, 189, 47, 0.15)',
+ errorDim: 'rgba(251, 73, 52, 0.15)',
+ infoDim: 'rgba(131, 165, 152, 0.15)',
+ diffAddition: '#b8bb26',
+ diffAdditionBg: 'rgba(184, 187, 38, 0.15)',
+ diffDeletion: '#fb4934',
+ diffDeletionBg: 'rgba(251, 73, 52, 0.15)',
+ overlay: 'rgba(0, 0, 0, 0.6)',
+ overlayHeavy: 'rgba(0, 0, 0, 0.8)',
+ hoverBg: 'rgba(255, 255, 255, 0.06)',
+ activeBg: 'rgba(255, 255, 255, 0.15)',
+ shadow: 'rgba(0, 0, 0, 0.3)',
},
},
// Light themes
@@ -153,6 +255,23 @@ export const THEMES: Record = {
success: '#1a7f37',
warning: '#9a6700',
error: '#cf222e',
+ info: '#0969da',
+ successForeground: '#ffffff',
+ warningForeground: '#ffffff',
+ errorForeground: '#ffffff',
+ successDim: 'rgba(26, 127, 55, 0.1)',
+ warningDim: 'rgba(154, 103, 0, 0.1)',
+ errorDim: 'rgba(207, 34, 46, 0.1)',
+ infoDim: 'rgba(9, 105, 218, 0.1)',
+ diffAddition: '#1a7f37',
+ diffAdditionBg: 'rgba(26, 127, 55, 0.1)',
+ diffDeletion: '#cf222e',
+ diffDeletionBg: 'rgba(207, 34, 46, 0.1)',
+ overlay: 'rgba(0, 0, 0, 0.5)',
+ overlayHeavy: 'rgba(0, 0, 0, 0.7)',
+ hoverBg: 'rgba(0, 0, 0, 0.04)',
+ activeBg: 'rgba(0, 0, 0, 0.1)',
+ shadow: 'rgba(0, 0, 0, 0.15)',
},
},
'solarized-light': {
@@ -173,6 +292,23 @@ export const THEMES: Record = {
success: '#859900',
warning: '#b58900',
error: '#dc322f',
+ info: '#268bd2',
+ successForeground: '#fdf6e3',
+ warningForeground: '#fdf6e3',
+ errorForeground: '#fdf6e3',
+ successDim: 'rgba(133, 153, 0, 0.1)',
+ warningDim: 'rgba(181, 137, 0, 0.1)',
+ errorDim: 'rgba(220, 50, 47, 0.1)',
+ infoDim: 'rgba(38, 139, 210, 0.1)',
+ diffAddition: '#859900',
+ diffAdditionBg: 'rgba(133, 153, 0, 0.1)',
+ diffDeletion: '#dc322f',
+ diffDeletionBg: 'rgba(220, 50, 47, 0.1)',
+ overlay: 'rgba(0, 0, 0, 0.5)',
+ overlayHeavy: 'rgba(0, 0, 0, 0.7)',
+ hoverBg: 'rgba(0, 0, 0, 0.04)',
+ activeBg: 'rgba(0, 0, 0, 0.1)',
+ shadow: 'rgba(0, 0, 0, 0.15)',
},
},
'one-light': {
@@ -193,6 +329,23 @@ export const THEMES: Record = {
success: '#50a14f',
warning: '#c18401',
error: '#e45649',
+ info: '#4078f2',
+ successForeground: '#ffffff',
+ warningForeground: '#ffffff',
+ errorForeground: '#ffffff',
+ successDim: 'rgba(80, 161, 79, 0.1)',
+ warningDim: 'rgba(193, 132, 1, 0.1)',
+ errorDim: 'rgba(228, 86, 73, 0.1)',
+ infoDim: 'rgba(64, 120, 242, 0.1)',
+ diffAddition: '#50a14f',
+ diffAdditionBg: 'rgba(80, 161, 79, 0.1)',
+ diffDeletion: '#e45649',
+ diffDeletionBg: 'rgba(228, 86, 73, 0.1)',
+ overlay: 'rgba(0, 0, 0, 0.5)',
+ overlayHeavy: 'rgba(0, 0, 0, 0.7)',
+ hoverBg: 'rgba(0, 0, 0, 0.04)',
+ activeBg: 'rgba(0, 0, 0, 0.1)',
+ shadow: 'rgba(0, 0, 0, 0.15)',
},
},
'gruvbox-light': {
@@ -213,6 +366,23 @@ export const THEMES: Record = {
success: '#98971a',
warning: '#d79921',
error: '#cc241d',
+ info: '#458588',
+ successForeground: '#fbf1c7',
+ warningForeground: '#fbf1c7',
+ errorForeground: '#fbf1c7',
+ successDim: 'rgba(152, 151, 26, 0.1)',
+ warningDim: 'rgba(215, 153, 33, 0.1)',
+ errorDim: 'rgba(204, 36, 29, 0.1)',
+ infoDim: 'rgba(69, 133, 136, 0.1)',
+ diffAddition: '#98971a',
+ diffAdditionBg: 'rgba(152, 151, 26, 0.1)',
+ diffDeletion: '#cc241d',
+ diffDeletionBg: 'rgba(204, 36, 29, 0.1)',
+ overlay: 'rgba(0, 0, 0, 0.5)',
+ overlayHeavy: 'rgba(0, 0, 0, 0.7)',
+ hoverBg: 'rgba(0, 0, 0, 0.04)',
+ activeBg: 'rgba(0, 0, 0, 0.1)',
+ shadow: 'rgba(0, 0, 0, 0.15)',
},
},
'catppuccin-latte': {
@@ -233,6 +403,23 @@ export const THEMES: Record = {
success: '#40a02b',
warning: '#fe640b',
error: '#d20f39',
+ info: '#1e66f5',
+ successForeground: '#ffffff',
+ warningForeground: '#ffffff',
+ errorForeground: '#ffffff',
+ successDim: 'rgba(64, 160, 43, 0.1)',
+ warningDim: 'rgba(254, 100, 11, 0.1)',
+ errorDim: 'rgba(210, 15, 57, 0.1)',
+ infoDim: 'rgba(30, 102, 245, 0.1)',
+ diffAddition: '#40a02b',
+ diffAdditionBg: 'rgba(64, 160, 43, 0.1)',
+ diffDeletion: '#d20f39',
+ diffDeletionBg: 'rgba(210, 15, 57, 0.1)',
+ overlay: 'rgba(0, 0, 0, 0.5)',
+ overlayHeavy: 'rgba(0, 0, 0, 0.7)',
+ hoverBg: 'rgba(0, 0, 0, 0.04)',
+ activeBg: 'rgba(0, 0, 0, 0.1)',
+ shadow: 'rgba(0, 0, 0, 0.15)',
},
},
'ayu-light': {
@@ -253,6 +440,23 @@ export const THEMES: Record = {
success: '#86b300',
warning: '#f2ae49',
error: '#f07171',
+ info: '#399ee6',
+ successForeground: '#1a1a1a',
+ warningForeground: '#1a1a1a',
+ errorForeground: '#ffffff',
+ successDim: 'rgba(134, 179, 0, 0.1)',
+ warningDim: 'rgba(242, 174, 73, 0.1)',
+ errorDim: 'rgba(240, 113, 113, 0.1)',
+ infoDim: 'rgba(57, 158, 230, 0.1)',
+ diffAddition: '#86b300',
+ diffAdditionBg: 'rgba(134, 179, 0, 0.1)',
+ diffDeletion: '#f07171',
+ diffDeletionBg: 'rgba(240, 113, 113, 0.1)',
+ overlay: 'rgba(0, 0, 0, 0.5)',
+ overlayHeavy: 'rgba(0, 0, 0, 0.7)',
+ hoverBg: 'rgba(0, 0, 0, 0.04)',
+ activeBg: 'rgba(0, 0, 0, 0.1)',
+ shadow: 'rgba(0, 0, 0, 0.15)',
},
},
// Vibe themes
@@ -274,6 +478,23 @@ export const THEMES: Record = {
success: '#7cb342',
warning: '#d4af37',
error: '#da70d6',
+ info: '#b89fd0',
+ successForeground: '#1a0f24',
+ warningForeground: '#1a0f24',
+ errorForeground: '#1a0f24',
+ successDim: 'rgba(124, 179, 66, 0.15)',
+ warningDim: 'rgba(212, 175, 55, 0.15)',
+ errorDim: 'rgba(218, 112, 214, 0.15)',
+ infoDim: 'rgba(184, 159, 208, 0.15)',
+ diffAddition: '#7cb342',
+ diffAdditionBg: 'rgba(124, 179, 66, 0.15)',
+ diffDeletion: '#da70d6',
+ diffDeletionBg: 'rgba(218, 112, 214, 0.15)',
+ overlay: 'rgba(0, 0, 0, 0.6)',
+ overlayHeavy: 'rgba(0, 0, 0, 0.8)',
+ hoverBg: 'rgba(255, 255, 255, 0.06)',
+ activeBg: 'rgba(255, 255, 255, 0.15)',
+ shadow: 'rgba(0, 0, 0, 0.3)',
},
},
'maestros-choice': {
@@ -294,6 +515,23 @@ export const THEMES: Record = {
success: '#66d9a0',
warning: '#f4c430',
error: '#e05070',
+ info: '#7aa2f7',
+ successForeground: '#1a1a24',
+ warningForeground: '#1a1a24',
+ errorForeground: '#1a1a24',
+ successDim: 'rgba(102, 217, 160, 0.15)',
+ warningDim: 'rgba(244, 196, 48, 0.15)',
+ errorDim: 'rgba(224, 80, 112, 0.15)',
+ infoDim: 'rgba(122, 162, 247, 0.15)',
+ diffAddition: '#66d9a0',
+ diffAdditionBg: 'rgba(102, 217, 160, 0.15)',
+ diffDeletion: '#e05070',
+ diffDeletionBg: 'rgba(224, 80, 112, 0.15)',
+ overlay: 'rgba(0, 0, 0, 0.6)',
+ overlayHeavy: 'rgba(0, 0, 0, 0.8)',
+ hoverBg: 'rgba(255, 255, 255, 0.06)',
+ activeBg: 'rgba(255, 255, 255, 0.15)',
+ shadow: 'rgba(0, 0, 0, 0.3)',
},
},
'dre-synth': {
@@ -303,17 +541,34 @@ export const THEMES: Record = {
colors: {
bgMain: '#0d0221',
bgSidebar: '#0a0118',
- bgActivity: '#150530',
- border: '#00d4aa',
+ bgActivity: '#1a0838',
+ border: '#1a3a4a',
textMain: '#f0e6ff',
textDim: '#60e0d0',
accent: '#00ffcc',
accentDim: 'rgba(0, 255, 204, 0.25)',
accentText: '#40ffdd',
accentForeground: '#0d0221',
- success: '#00ffcc',
- warning: '#ff2a6d',
+ success: '#33ff99',
+ warning: '#ff9944',
error: '#ff2a6d',
+ info: '#40ffdd',
+ successForeground: '#0d0221',
+ warningForeground: '#0d0221',
+ errorForeground: '#0d0221',
+ successDim: 'rgba(51, 255, 153, 0.15)',
+ warningDim: 'rgba(255, 153, 68, 0.15)',
+ errorDim: 'rgba(255, 42, 109, 0.15)',
+ infoDim: 'rgba(64, 255, 221, 0.15)',
+ diffAddition: '#33ff99',
+ diffAdditionBg: 'rgba(51, 255, 153, 0.15)',
+ diffDeletion: '#ff2a6d',
+ diffDeletionBg: 'rgba(255, 42, 109, 0.15)',
+ overlay: 'rgba(0, 0, 0, 0.6)',
+ overlayHeavy: 'rgba(0, 0, 0, 0.8)',
+ hoverBg: 'rgba(255, 255, 255, 0.06)',
+ activeBg: 'rgba(255, 255, 255, 0.15)',
+ shadow: 'rgba(0, 0, 0, 0.3)',
},
},
inquest: {
@@ -334,6 +589,23 @@ export const THEMES: Record = {
success: '#f5f5f5',
warning: '#cc0033',
error: '#cc0033',
+ info: '#888888',
+ successForeground: '#0a0a0a',
+ warningForeground: '#ffffff',
+ errorForeground: '#ffffff',
+ successDim: 'rgba(245, 245, 245, 0.15)',
+ warningDim: 'rgba(204, 0, 51, 0.15)',
+ errorDim: 'rgba(204, 0, 51, 0.15)',
+ infoDim: 'rgba(136, 136, 136, 0.15)',
+ diffAddition: '#f5f5f5',
+ diffAdditionBg: 'rgba(245, 245, 245, 0.15)',
+ diffDeletion: '#cc0033',
+ diffDeletionBg: 'rgba(204, 0, 51, 0.15)',
+ overlay: 'rgba(0, 0, 0, 0.6)',
+ overlayHeavy: 'rgba(0, 0, 0, 0.8)',
+ hoverBg: 'rgba(255, 255, 255, 0.06)',
+ activeBg: 'rgba(255, 255, 255, 0.15)',
+ shadow: 'rgba(0, 0, 0, 0.3)',
},
},
// Custom theme - user-configurable, defaults to Dracula
@@ -355,6 +627,23 @@ export const THEMES: Record = {
success: '#50fa7b',
warning: '#ffb86c',
error: '#ff5555',
+ info: '#8be9fd',
+ successForeground: '#282a36',
+ warningForeground: '#282a36',
+ errorForeground: '#282a36',
+ successDim: 'rgba(80, 250, 123, 0.15)',
+ warningDim: 'rgba(255, 184, 108, 0.15)',
+ errorDim: 'rgba(255, 85, 85, 0.15)',
+ infoDim: 'rgba(139, 233, 253, 0.15)',
+ diffAddition: '#50fa7b',
+ diffAdditionBg: 'rgba(80, 250, 123, 0.15)',
+ diffDeletion: '#ff5555',
+ diffDeletionBg: 'rgba(255, 85, 85, 0.15)',
+ overlay: 'rgba(0, 0, 0, 0.6)',
+ overlayHeavy: 'rgba(0, 0, 0, 0.8)',
+ hoverBg: 'rgba(255, 255, 255, 0.06)',
+ activeBg: 'rgba(255, 255, 255, 0.15)',
+ shadow: 'rgba(0, 0, 0, 0.3)',
},
},
};
diff --git a/src/web/components/ThemeProvider.tsx b/src/web/components/ThemeProvider.tsx
index 4231255b0..8df3a5cd5 100644
--- a/src/web/components/ThemeProvider.tsx
+++ b/src/web/components/ThemeProvider.tsx
@@ -52,6 +52,23 @@ const defaultDarkTheme: Theme = {
success: '#22c55e',
warning: '#eab308',
error: '#ef4444',
+ info: '#6366f1',
+ successForeground: '#0b0b0d',
+ warningForeground: '#0b0b0d',
+ errorForeground: '#0b0b0d',
+ successDim: 'rgba(34, 197, 94, 0.15)',
+ warningDim: 'rgba(234, 179, 8, 0.15)',
+ errorDim: 'rgba(239, 68, 68, 0.15)',
+ infoDim: 'rgba(99, 102, 241, 0.15)',
+ diffAddition: '#22c55e',
+ diffAdditionBg: 'rgba(34, 197, 94, 0.15)',
+ diffDeletion: '#ef4444',
+ diffDeletionBg: 'rgba(239, 68, 68, 0.15)',
+ overlay: 'rgba(0, 0, 0, 0.6)',
+ overlayHeavy: 'rgba(0, 0, 0, 0.8)',
+ hoverBg: 'rgba(255, 255, 255, 0.06)',
+ activeBg: 'rgba(255, 255, 255, 0.15)',
+ shadow: 'rgba(0, 0, 0, 0.3)',
},
};
@@ -77,6 +94,23 @@ const defaultLightTheme: Theme = {
success: '#1a7f37',
warning: '#9a6700',
error: '#cf222e',
+ info: '#0969da',
+ successForeground: '#ffffff',
+ warningForeground: '#ffffff',
+ errorForeground: '#ffffff',
+ successDim: 'rgba(26, 127, 55, 0.1)',
+ warningDim: 'rgba(154, 103, 0, 0.1)',
+ errorDim: 'rgba(207, 34, 46, 0.1)',
+ infoDim: 'rgba(9, 105, 218, 0.1)',
+ diffAddition: '#1a7f37',
+ diffAdditionBg: 'rgba(26, 127, 55, 0.1)',
+ diffDeletion: '#cf222e',
+ diffDeletionBg: 'rgba(207, 34, 46, 0.1)',
+ overlay: 'rgba(0, 0, 0, 0.5)',
+ overlayHeavy: 'rgba(0, 0, 0, 0.7)',
+ hoverBg: 'rgba(0, 0, 0, 0.04)',
+ activeBg: 'rgba(0, 0, 0, 0.1)',
+ shadow: 'rgba(0, 0, 0, 0.15)',
},
};
diff --git a/src/web/utils/cssCustomProperties.ts b/src/web/utils/cssCustomProperties.ts
index 1ffa3b504..c196379c9 100644
--- a/src/web/utils/cssCustomProperties.ts
+++ b/src/web/utils/cssCustomProperties.ts
@@ -30,6 +30,23 @@ export type ThemeCSSProperty =
| '--maestro-success'
| '--maestro-warning'
| '--maestro-error'
+ | '--maestro-info'
+ | '--maestro-success-foreground'
+ | '--maestro-warning-foreground'
+ | '--maestro-error-foreground'
+ | '--maestro-success-dim'
+ | '--maestro-warning-dim'
+ | '--maestro-error-dim'
+ | '--maestro-info-dim'
+ | '--maestro-diff-addition'
+ | '--maestro-diff-addition-bg'
+ | '--maestro-diff-deletion'
+ | '--maestro-diff-deletion-bg'
+ | '--maestro-overlay'
+ | '--maestro-overlay-heavy'
+ | '--maestro-hover-bg'
+ | '--maestro-active-bg'
+ | '--maestro-shadow'
| '--maestro-mode';
/**
@@ -49,6 +66,23 @@ const colorToCSSProperty: Record = {
success: '--maestro-success',
warning: '--maestro-warning',
error: '--maestro-error',
+ info: '--maestro-info',
+ successForeground: '--maestro-success-foreground',
+ warningForeground: '--maestro-warning-foreground',
+ errorForeground: '--maestro-error-foreground',
+ successDim: '--maestro-success-dim',
+ warningDim: '--maestro-warning-dim',
+ errorDim: '--maestro-error-dim',
+ infoDim: '--maestro-info-dim',
+ diffAddition: '--maestro-diff-addition',
+ diffAdditionBg: '--maestro-diff-addition-bg',
+ diffDeletion: '--maestro-diff-deletion',
+ diffDeletionBg: '--maestro-diff-deletion-bg',
+ overlay: '--maestro-overlay',
+ overlayHeavy: '--maestro-overlay-heavy',
+ hoverBg: '--maestro-hover-bg',
+ activeBg: '--maestro-active-bg',
+ shadow: '--maestro-shadow',
};
/**
@@ -68,6 +102,23 @@ export const THEME_CSS_PROPERTIES: ThemeCSSProperty[] = [
'--maestro-success',
'--maestro-warning',
'--maestro-error',
+ '--maestro-info',
+ '--maestro-success-foreground',
+ '--maestro-warning-foreground',
+ '--maestro-error-foreground',
+ '--maestro-success-dim',
+ '--maestro-warning-dim',
+ '--maestro-error-dim',
+ '--maestro-info-dim',
+ '--maestro-diff-addition',
+ '--maestro-diff-addition-bg',
+ '--maestro-diff-deletion',
+ '--maestro-diff-deletion-bg',
+ '--maestro-overlay',
+ '--maestro-overlay-heavy',
+ '--maestro-hover-bg',
+ '--maestro-active-bg',
+ '--maestro-shadow',
'--maestro-mode',
];