@@ -1645,7 +1662,7 @@ export const MultiEditWidget: React.FC<{
Promise;
+ setCustomColors: (colors: Partial) => Promise;
+ isLoading: boolean;
+}
+
+const ThemeContext = createContext(undefined);
+
+const THEME_STORAGE_KEY = 'theme_preference';
+const CUSTOM_COLORS_STORAGE_KEY = 'theme_custom_colors';
+
+// Default custom theme colors (based on current dark theme)
+const DEFAULT_CUSTOM_COLORS: CustomThemeColors = {
+ background: 'oklch(0.12 0.01 240)',
+ foreground: 'oklch(0.98 0.01 240)',
+ card: 'oklch(0.14 0.01 240)',
+ cardForeground: 'oklch(0.98 0.01 240)',
+ primary: 'oklch(0.98 0.01 240)',
+ primaryForeground: 'oklch(0.12 0.01 240)',
+ secondary: 'oklch(0.16 0.01 240)',
+ secondaryForeground: 'oklch(0.98 0.01 240)',
+ muted: 'oklch(0.16 0.01 240)',
+ mutedForeground: 'oklch(0.65 0.01 240)',
+ accent: 'oklch(0.16 0.01 240)',
+ accentForeground: 'oklch(0.98 0.01 240)',
+ destructive: 'oklch(0.6 0.2 25)',
+ destructiveForeground: 'oklch(0.98 0.01 240)',
+ border: 'oklch(0.16 0.01 240)',
+ input: 'oklch(0.16 0.01 240)',
+ ring: 'oklch(0.98 0.01 240)',
+};
+
+export const ThemeProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
+ const [theme, setThemeState] = useState('dark');
+ const [customColors, setCustomColorsState] = useState(DEFAULT_CUSTOM_COLORS);
+ const [isLoading, setIsLoading] = useState(true);
+
+ // Load theme preference and custom colors from storage
+ useEffect(() => {
+ const loadTheme = async () => {
+ try {
+ // Load theme preference
+ const savedTheme = await api.getSetting(THEME_STORAGE_KEY);
+
+ if (savedTheme) {
+ const themeMode = savedTheme as ThemeMode;
+ setThemeState(themeMode);
+ applyTheme(themeMode, customColors);
+ }
+
+ // Load custom colors
+ const savedColors = await api.getSetting(CUSTOM_COLORS_STORAGE_KEY);
+
+ if (savedColors) {
+ const colors = JSON.parse(savedColors) as CustomThemeColors;
+ setCustomColorsState(colors);
+ if (theme === 'custom') {
+ applyTheme('custom', colors);
+ }
+ }
+ } catch (error) {
+ console.error('Failed to load theme settings:', error);
+ } finally {
+ setIsLoading(false);
+ }
+ };
+
+ loadTheme();
+ }, []);
+
+ // Apply theme to document
+ const applyTheme = useCallback((themeMode: ThemeMode, colors: CustomThemeColors) => {
+ const root = document.documentElement;
+
+ // Remove all theme classes
+ root.classList.remove('theme-dark', 'theme-gray', 'theme-light', 'theme-custom');
+
+ // Add new theme class
+ root.classList.add(`theme-${themeMode}`);
+
+ // If custom theme, apply custom colors as CSS variables
+ if (themeMode === 'custom') {
+ Object.entries(colors).forEach(([key, value]) => {
+ const cssVarName = `--color-${key.replace(/([A-Z])/g, '-$1').toLowerCase()}`;
+ root.style.setProperty(cssVarName, value);
+ });
+ } else {
+ // Clear custom CSS variables when not using custom theme
+ Object.keys(colors).forEach((key) => {
+ const cssVarName = `--color-${key.replace(/([A-Z])/g, '-$1').toLowerCase()}`;
+ root.style.removeProperty(cssVarName);
+ });
+ }
+ }, []);
+
+ const setTheme = useCallback(async (newTheme: ThemeMode) => {
+ try {
+ setIsLoading(true);
+
+ // Apply theme immediately
+ setThemeState(newTheme);
+ applyTheme(newTheme, customColors);
+
+ // Save to storage
+ await api.saveSetting(THEME_STORAGE_KEY, newTheme);
+ } catch (error) {
+ console.error('Failed to save theme preference:', error);
+ } finally {
+ setIsLoading(false);
+ }
+ }, [customColors, applyTheme]);
+
+ const setCustomColors = useCallback(async (colors: Partial) => {
+ try {
+ setIsLoading(true);
+
+ const newColors = { ...customColors, ...colors };
+ setCustomColorsState(newColors);
+
+ // Apply immediately if custom theme is active
+ if (theme === 'custom') {
+ applyTheme('custom', newColors);
+ }
+
+ // Save to storage
+ await api.saveSetting(CUSTOM_COLORS_STORAGE_KEY, JSON.stringify(newColors));
+ } catch (error) {
+ console.error('Failed to save custom colors:', error);
+ } finally {
+ setIsLoading(false);
+ }
+ }, [theme, customColors, applyTheme]);
+
+ const value: ThemeContextType = {
+ theme,
+ customColors,
+ setTheme,
+ setCustomColors,
+ isLoading,
+ };
+
+ return (
+
+ {children}
+
+ );
+};
+
+export const useThemeContext = () => {
+ const context = useContext(ThemeContext);
+ if (!context) {
+ throw new Error('useThemeContext must be used within a ThemeProvider');
+ }
+ return context;
+};
\ No newline at end of file
diff --git a/src/hooks/index.ts b/src/hooks/index.ts
index 34163e3..b3bc5d2 100644
--- a/src/hooks/index.ts
+++ b/src/hooks/index.ts
@@ -2,4 +2,5 @@
export { useLoadingState } from './useLoadingState';
export { useDebounce, useDebouncedCallback } from './useDebounce';
export { useApiCall } from './useApiCall';
-export { usePagination } from './usePagination';
\ No newline at end of file
+export { usePagination } from './usePagination';
+export { useTheme } from './useTheme';
\ No newline at end of file
diff --git a/src/hooks/useTheme.ts b/src/hooks/useTheme.ts
new file mode 100644
index 0000000..7a6bd7b
--- /dev/null
+++ b/src/hooks/useTheme.ts
@@ -0,0 +1,24 @@
+import { useThemeContext } from '../contexts/ThemeContext';
+
+/**
+ * Hook to access and control the theme system
+ *
+ * @returns {Object} Theme utilities and state
+ * @returns {ThemeMode} theme - Current theme mode ('dark' | 'gray' | 'light' | 'custom')
+ * @returns {CustomThemeColors} customColors - Custom theme color configuration
+ * @returns {Function} setTheme - Function to change the theme mode
+ * @returns {Function} setCustomColors - Function to update custom theme colors
+ * @returns {boolean} isLoading - Whether theme operations are in progress
+ *
+ * @example
+ * const { theme, setTheme } = useTheme();
+ *
+ * // Change theme
+ * await setTheme('light');
+ *
+ * // Update custom colors
+ * await setCustomColors({ background: 'oklch(0.98 0.01 240)' });
+ */
+export const useTheme = () => {
+ return useThemeContext();
+};
\ No newline at end of file
diff --git a/src/lib/api.ts b/src/lib/api.ts
index 1d89071..9a78640 100644
--- a/src/lib/api.ts
+++ b/src/lib/api.ts
@@ -1685,6 +1685,50 @@ export const api = {
}
},
+ // Theme settings helpers
+
+ /**
+ * Gets a setting from the app_settings table
+ * @param key - The setting key to retrieve
+ * @returns Promise resolving to the setting value or null if not found
+ */
+ async getSetting(key: string): Promise {
+ try {
+ // Use storageReadTable to safely query the app_settings table
+ const result = await this.storageReadTable('app_settings', 1, 1000);
+ const setting = result?.data?.find((row: any) => row.key === key);
+ return setting?.value || null;
+ } catch (error) {
+ console.error(`Failed to get setting ${key}:`, error);
+ return null;
+ }
+ },
+
+ /**
+ * Saves a setting to the app_settings table (insert or update)
+ * @param key - The setting key
+ * @param value - The setting value
+ * @returns Promise resolving when the setting is saved
+ */
+ async saveSetting(key: string, value: string): Promise {
+ try {
+ // Try to update first
+ try {
+ await this.storageUpdateRow(
+ 'app_settings',
+ { key },
+ { value }
+ );
+ } catch (updateError) {
+ // If update fails (row doesn't exist), insert new row
+ await this.storageInsertRow('app_settings', { key, value });
+ }
+ } catch (error) {
+ console.error(`Failed to save setting ${key}:`, error);
+ throw error;
+ }
+ },
+
/**
* Get hooks configuration for a specific scope
* @param scope - The configuration scope: 'user', 'project', or 'local'
diff --git a/src/lib/claudeSyntaxTheme.ts b/src/lib/claudeSyntaxTheme.ts
index 61b67fa..a4aa9ed 100644
--- a/src/lib/claudeSyntaxTheme.ts
+++ b/src/lib/claudeSyntaxTheme.ts
@@ -1,175 +1,258 @@
+import { ThemeMode } from '@/contexts/ThemeContext';
+
/**
- * Claude-themed syntax highlighting theme
- * Features orange, purple, and violet colors to match Claude's aesthetic
+ * Claude-themed syntax highlighting theme factory
+ * Returns different syntax themes based on the current theme mode
+ *
+ * @param theme - The current theme mode
+ * @returns Prism syntax highlighting theme object
*/
-export const claudeSyntaxTheme: any = {
- 'code[class*="language-"]': {
- color: '#e3e8f0',
- background: 'transparent',
- textShadow: 'none',
- fontFamily: 'var(--font-mono)',
- fontSize: '0.875em',
- textAlign: 'left',
- whiteSpace: 'pre',
- wordSpacing: 'normal',
- wordBreak: 'normal',
- wordWrap: 'normal',
- lineHeight: '1.5',
- MozTabSize: '4',
- OTabSize: '4',
- tabSize: '4',
- WebkitHyphens: 'none',
- MozHyphens: 'none',
- msHyphens: 'none',
- hyphens: 'none',
- },
- 'pre[class*="language-"]': {
- color: '#e3e8f0',
- background: 'transparent',
- textShadow: 'none',
- fontFamily: 'var(--font-mono)',
- fontSize: '0.875em',
- textAlign: 'left',
- whiteSpace: 'pre',
- wordSpacing: 'normal',
- wordBreak: 'normal',
- wordWrap: 'normal',
- lineHeight: '1.5',
- MozTabSize: '4',
- OTabSize: '4',
- tabSize: '4',
- WebkitHyphens: 'none',
- MozHyphens: 'none',
- msHyphens: 'none',
- hyphens: 'none',
- padding: '1em',
- margin: '0',
- overflow: 'auto',
- },
- ':not(pre) > code[class*="language-"]': {
- background: 'rgba(139, 92, 246, 0.1)',
- padding: '0.1em 0.3em',
- borderRadius: '0.3em',
- whiteSpace: 'normal',
- },
- 'comment': {
- color: '#6b7280',
- fontStyle: 'italic',
- },
- 'prolog': {
- color: '#6b7280',
- },
- 'doctype': {
- color: '#6b7280',
- },
- 'cdata': {
- color: '#6b7280',
- },
- 'punctuation': {
- color: '#9ca3af',
- },
- 'namespace': {
- opacity: '0.7',
- },
- 'property': {
- color: '#f59e0b', // Amber/Orange
- },
- 'tag': {
- color: '#8b5cf6', // Violet
- },
- 'boolean': {
- color: '#f59e0b', // Amber/Orange
- },
- 'number': {
- color: '#f59e0b', // Amber/Orange
- },
- 'constant': {
- color: '#f59e0b', // Amber/Orange
- },
- 'symbol': {
- color: '#f59e0b', // Amber/Orange
- },
- 'deleted': {
- color: '#ef4444',
- },
- 'selector': {
- color: '#a78bfa', // Light Purple
- },
- 'attr-name': {
- color: '#a78bfa', // Light Purple
- },
- 'string': {
- color: '#10b981', // Emerald Green
- },
- 'char': {
- color: '#10b981', // Emerald Green
- },
- 'builtin': {
- color: '#8b5cf6', // Violet
- },
- 'url': {
- color: '#10b981', // Emerald Green
- },
- 'inserted': {
- color: '#10b981', // Emerald Green
- },
- 'entity': {
- color: '#a78bfa', // Light Purple
- cursor: 'help',
- },
- 'atrule': {
- color: '#c084fc', // Light Violet
- },
- 'attr-value': {
- color: '#10b981', // Emerald Green
- },
- 'keyword': {
- color: '#c084fc', // Light Violet
- },
- 'function': {
- color: '#818cf8', // Indigo
- },
- 'class-name': {
- color: '#f59e0b', // Amber/Orange
- },
- 'regex': {
- color: '#06b6d4', // Cyan
- },
- 'important': {
- color: '#f59e0b', // Amber/Orange
- fontWeight: 'bold',
- },
- 'variable': {
- color: '#a78bfa', // Light Purple
- },
- 'bold': {
- fontWeight: 'bold',
- },
- 'italic': {
- fontStyle: 'italic',
- },
- 'operator': {
- color: '#9ca3af',
- },
- 'script': {
- color: '#e3e8f0',
- },
- 'parameter': {
- color: '#fbbf24', // Yellow
- },
- 'method': {
- color: '#818cf8', // Indigo
- },
- 'field': {
- color: '#f59e0b', // Amber/Orange
- },
- 'annotation': {
- color: '#6b7280',
- },
- 'type': {
- color: '#a78bfa', // Light Purple
- },
- 'module': {
- color: '#8b5cf6', // Violet
- },
-};
\ No newline at end of file
+export const getClaudeSyntaxTheme = (theme: ThemeMode): any => {
+ const themes = {
+ dark: {
+ base: '#e3e8f0',
+ background: 'transparent',
+ comment: '#6b7280',
+ punctuation: '#9ca3af',
+ property: '#f59e0b', // Amber/Orange
+ tag: '#8b5cf6', // Violet
+ string: '#10b981', // Emerald Green
+ function: '#818cf8', // Indigo
+ keyword: '#c084fc', // Light Violet
+ variable: '#a78bfa', // Light Purple
+ operator: '#9ca3af',
+ },
+ gray: {
+ base: '#e3e8f0',
+ background: 'transparent',
+ comment: '#71717a',
+ punctuation: '#a1a1aa',
+ property: '#fbbf24', // Yellow
+ tag: '#a78bfa', // Light Purple
+ string: '#34d399', // Green
+ function: '#93bbfc', // Light Blue
+ keyword: '#d8b4fe', // Light Purple
+ variable: '#c084fc', // Purple
+ operator: '#a1a1aa',
+ },
+ light: {
+ base: '#1f2937',
+ background: 'transparent',
+ comment: '#9ca3af',
+ punctuation: '#6b7280',
+ property: '#dc2626', // Red
+ tag: '#7c3aed', // Purple
+ string: '#059669', // Green
+ function: '#2563eb', // Blue
+ keyword: '#9333ea', // Purple
+ variable: '#8b5cf6', // Violet
+ operator: '#6b7280',
+ },
+ white: {
+ base: '#000000',
+ background: 'transparent',
+ comment: '#6b7280',
+ punctuation: '#374151',
+ property: '#dc2626', // Red
+ tag: '#5b21b6', // Deep Purple
+ string: '#047857', // Dark Green
+ function: '#1e40af', // Dark Blue
+ keyword: '#6b21a8', // Dark Purple
+ variable: '#6d28d9', // Dark Violet
+ operator: '#374151',
+ },
+ custom: {
+ // Default to dark theme colors for custom
+ base: '#e3e8f0',
+ background: 'transparent',
+ comment: '#6b7280',
+ punctuation: '#9ca3af',
+ property: '#f59e0b',
+ tag: '#8b5cf6',
+ string: '#10b981',
+ function: '#818cf8',
+ keyword: '#c084fc',
+ variable: '#a78bfa',
+ operator: '#9ca3af',
+ }
+ };
+
+ const colors = themes[theme] || themes.dark;
+
+ return {
+ 'code[class*="language-"]': {
+ color: colors.base,
+ background: colors.background,
+ textShadow: 'none',
+ fontFamily: 'var(--font-mono)',
+ fontSize: '0.875em',
+ textAlign: 'left',
+ whiteSpace: 'pre',
+ wordSpacing: 'normal',
+ wordBreak: 'normal',
+ wordWrap: 'normal',
+ lineHeight: '1.5',
+ MozTabSize: '4',
+ OTabSize: '4',
+ tabSize: '4',
+ WebkitHyphens: 'none',
+ MozHyphens: 'none',
+ msHyphens: 'none',
+ hyphens: 'none',
+ },
+ 'pre[class*="language-"]': {
+ color: colors.base,
+ background: colors.background,
+ textShadow: 'none',
+ fontFamily: 'var(--font-mono)',
+ fontSize: '0.875em',
+ textAlign: 'left',
+ whiteSpace: 'pre',
+ wordSpacing: 'normal',
+ wordBreak: 'normal',
+ wordWrap: 'normal',
+ lineHeight: '1.5',
+ MozTabSize: '4',
+ OTabSize: '4',
+ tabSize: '4',
+ WebkitHyphens: 'none',
+ MozHyphens: 'none',
+ msHyphens: 'none',
+ hyphens: 'none',
+ padding: '1em',
+ margin: '0',
+ overflow: 'auto',
+ },
+ ':not(pre) > code[class*="language-"]': {
+ background: theme === 'light' || theme === 'white'
+ ? 'rgba(139, 92, 246, 0.1)'
+ : 'rgba(139, 92, 246, 0.1)',
+ padding: '0.1em 0.3em',
+ borderRadius: '0.3em',
+ whiteSpace: 'normal',
+ },
+ 'comment': {
+ color: colors.comment,
+ fontStyle: 'italic',
+ },
+ 'prolog': {
+ color: colors.comment,
+ },
+ 'doctype': {
+ color: colors.comment,
+ },
+ 'cdata': {
+ color: colors.comment,
+ },
+ 'punctuation': {
+ color: colors.punctuation,
+ },
+ 'namespace': {
+ opacity: '0.7',
+ },
+ 'property': {
+ color: colors.property,
+ },
+ 'tag': {
+ color: colors.tag,
+ },
+ 'boolean': {
+ color: colors.property,
+ },
+ 'number': {
+ color: colors.property,
+ },
+ 'constant': {
+ color: colors.property,
+ },
+ 'symbol': {
+ color: colors.property,
+ },
+ 'deleted': {
+ color: '#ef4444',
+ },
+ 'selector': {
+ color: colors.variable,
+ },
+ 'attr-name': {
+ color: colors.variable,
+ },
+ 'string': {
+ color: colors.string,
+ },
+ 'char': {
+ color: colors.string,
+ },
+ 'builtin': {
+ color: colors.tag,
+ },
+ 'url': {
+ color: colors.string,
+ },
+ 'inserted': {
+ color: colors.string,
+ },
+ 'entity': {
+ color: colors.variable,
+ cursor: 'help',
+ },
+ 'atrule': {
+ color: colors.keyword,
+ },
+ 'attr-value': {
+ color: colors.string,
+ },
+ 'keyword': {
+ color: colors.keyword,
+ },
+ 'function': {
+ color: colors.function,
+ },
+ 'class-name': {
+ color: colors.property,
+ },
+ 'regex': {
+ color: '#06b6d4', // Cyan
+ },
+ 'important': {
+ color: colors.property,
+ fontWeight: 'bold',
+ },
+ 'variable': {
+ color: colors.variable,
+ },
+ 'bold': {
+ fontWeight: 'bold',
+ },
+ 'italic': {
+ fontStyle: 'italic',
+ },
+ 'operator': {
+ color: colors.operator,
+ },
+ 'script': {
+ color: colors.base,
+ },
+ 'parameter': {
+ color: colors.property,
+ },
+ 'method': {
+ color: colors.function,
+ },
+ 'field': {
+ color: colors.property,
+ },
+ 'annotation': {
+ color: colors.comment,
+ },
+ 'type': {
+ color: colors.variable,
+ },
+ 'module': {
+ color: colors.tag,
+ },
+ };
+};
+
+// Export default dark theme for backward compatibility
+export const claudeSyntaxTheme = getClaudeSyntaxTheme('dark');
\ No newline at end of file
diff --git a/src/styles.css b/src/styles.css
index 5b1fa96..7615fca 100644
--- a/src/styles.css
+++ b/src/styles.css
@@ -43,6 +43,95 @@
--ease-bounce: cubic-bezier(0.68, -0.55, 0.265, 1.55);
}
+/* Theme Variations */
+/* Default is dark theme - already defined above */
+
+/* Light Theme */
+.theme-light {
+ --color-background: oklch(0.98 0.01 240);
+ --color-foreground: oklch(0.12 0.01 240);
+ --color-card: oklch(0.96 0.01 240);
+ --color-card-foreground: oklch(0.12 0.01 240);
+ --color-popover: oklch(0.98 0.01 240);
+ --color-popover-foreground: oklch(0.12 0.01 240);
+ --color-primary: oklch(0.12 0.01 240);
+ --color-primary-foreground: oklch(0.98 0.01 240);
+ --color-secondary: oklch(0.94 0.01 240);
+ --color-secondary-foreground: oklch(0.12 0.01 240);
+ --color-muted: oklch(0.94 0.01 240);
+ --color-muted-foreground: oklch(0.45 0.01 240);
+ --color-accent: oklch(0.94 0.01 240);
+ --color-accent-foreground: oklch(0.12 0.01 240);
+ --color-destructive: oklch(0.6 0.2 25);
+ --color-destructive-foreground: oklch(0.98 0.01 240);
+ --color-border: oklch(0.90 0.01 240);
+ --color-input: oklch(0.90 0.01 240);
+ --color-ring: oklch(0.52 0.015 240);
+
+ /* Additional colors for status messages */
+ --color-green-500: oklch(0.62 0.20 142);
+ --color-green-600: oklch(0.54 0.22 142);
+}
+
+/* Gray Theme */
+.theme-gray {
+ --color-background: oklch(0.22 0.01 240);
+ --color-foreground: oklch(0.98 0.01 240);
+ --color-card: oklch(0.26 0.01 240);
+ --color-card-foreground: oklch(0.98 0.01 240);
+ --color-popover: oklch(0.22 0.01 240);
+ --color-popover-foreground: oklch(0.98 0.01 240);
+ --color-primary: oklch(0.98 0.01 240);
+ --color-primary-foreground: oklch(0.22 0.01 240);
+ --color-secondary: oklch(0.30 0.01 240);
+ --color-secondary-foreground: oklch(0.98 0.01 240);
+ --color-muted: oklch(0.30 0.01 240);
+ --color-muted-foreground: oklch(0.70 0.01 240);
+ --color-accent: oklch(0.30 0.01 240);
+ --color-accent-foreground: oklch(0.98 0.01 240);
+ --color-destructive: oklch(0.6 0.2 25);
+ --color-destructive-foreground: oklch(0.98 0.01 240);
+ --color-border: oklch(0.30 0.01 240);
+ --color-input: oklch(0.30 0.01 240);
+ --color-ring: oklch(0.60 0.015 240);
+
+ /* Additional colors for status messages */
+ --color-green-500: oklch(0.72 0.20 142);
+ --color-green-600: oklch(0.64 0.22 142);
+}
+
+/* White Theme (High Contrast Light) */
+.theme-white {
+ --color-background: oklch(1.0 0 240);
+ --color-foreground: oklch(0.0 0 240);
+ --color-card: oklch(0.98 0.01 240);
+ --color-card-foreground: oklch(0.0 0 240);
+ --color-popover: oklch(1.0 0 240);
+ --color-popover-foreground: oklch(0.0 0 240);
+ --color-primary: oklch(0.0 0 240);
+ --color-primary-foreground: oklch(1.0 0 240);
+ --color-secondary: oklch(0.96 0.01 240);
+ --color-secondary-foreground: oklch(0.0 0 240);
+ --color-muted: oklch(0.96 0.01 240);
+ --color-muted-foreground: oklch(0.35 0.01 240);
+ --color-accent: oklch(0.96 0.01 240);
+ --color-accent-foreground: oklch(0.0 0 240);
+ --color-destructive: oklch(0.55 0.25 25);
+ --color-destructive-foreground: oklch(1.0 0 240);
+ --color-border: oklch(0.85 0.01 240);
+ --color-input: oklch(0.85 0.01 240);
+ --color-ring: oklch(0.40 0.015 240);
+
+ /* Additional colors for status messages */
+ --color-green-500: oklch(0.55 0.25 142);
+ --color-green-600: oklch(0.47 0.27 142);
+}
+
+/* Custom Theme - CSS variables will be set dynamically by ThemeContext */
+.theme-custom {
+ /* Custom theme variables are applied dynamically via JavaScript */
+}
+
/* Reset and base styles */
* {
border-color: var(--color-border);
@@ -157,8 +246,10 @@ button:focus-visible,
}
}
-/* Markdown Editor Dark Mode Styles */
-[data-color-mode="dark"] {
+/* Markdown Editor Theme-aware Styles */
+[data-color-mode="dark"],
+.theme-dark [data-color-mode="dark"],
+.theme-gray [data-color-mode="dark"] {
--color-border-default: rgb(48, 54, 61);
--color-canvas-default: rgb(13, 17, 23);
--color-canvas-subtle: rgb(22, 27, 34);
@@ -169,6 +260,19 @@ button:focus-visible,
--color-danger-fg: rgb(248, 81, 73);
}
+[data-color-mode="light"],
+.theme-light [data-color-mode="light"],
+.theme-white [data-color-mode="light"] {
+ --color-border-default: rgb(216, 222, 228);
+ --color-canvas-default: rgb(255, 255, 255);
+ --color-canvas-subtle: rgb(246, 248, 250);
+ --color-fg-default: rgb(31, 35, 40);
+ --color-fg-muted: rgb(101, 109, 118);
+ --color-fg-subtle: rgb(149, 157, 165);
+ --color-accent-fg: rgb(9, 105, 218);
+ --color-danger-fg: rgb(207, 34, 46);
+}
+
.w-md-editor {
background-color: transparent !important;
color: var(--color-foreground) !important;