feat: implement comprehensive theming system

- Add ThemeContext with support for dark, gray, light, and custom themes
- Create theme switching UI in Settings with theme selector
- Add custom color editor for custom theme mode
- Update styles.css with theme-specific CSS variables
- Add theme storage API methods for persistence
- Update syntax highlighting to match selected theme
- Wrap App with ThemeProvider for global theme access

The theming system allows users to switch between predefined themes
or create their own custom theme with live color editing.
This commit is contained in:
Mufeed VH
2025-07-28 15:05:46 +05:30
parent 4ddb6a1995
commit c87d36e118
10 changed files with 809 additions and 192 deletions

View File

@@ -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
},
};
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');