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:
@@ -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');
|
Reference in New Issue
Block a user