292 lines
7.1 KiB
TypeScript
292 lines
7.1 KiB
TypeScript
// Theme configuration for the application
|
|
export const themeConfig = {
|
|
colors: {
|
|
// Primary colors (Green)
|
|
primary: {
|
|
50: '#f0fdf4',
|
|
100: '#dcfce7',
|
|
200: '#bbf7d0',
|
|
300: '#86efac',
|
|
400: '#4ade80',
|
|
500: '#22c55e',
|
|
600: '#16a34a',
|
|
700: '#15803d',
|
|
800: '#166534',
|
|
900: '#14532d',
|
|
950: '#052e16',
|
|
},
|
|
|
|
// Secondary colors (Blue)
|
|
secondary: {
|
|
50: '#eff6ff',
|
|
100: '#dbeafe',
|
|
200: '#bfdbfe',
|
|
300: '#93c5fd',
|
|
400: '#60a5fa',
|
|
500: '#3b82f6',
|
|
600: '#2563eb',
|
|
700: '#1d4ed8',
|
|
800: '#1e40af',
|
|
900: '#1e3a8a',
|
|
950: '#172554',
|
|
},
|
|
|
|
// Neutral colors
|
|
neutral: {
|
|
50: '#fafafa',
|
|
100: '#f5f5f5',
|
|
200: '#e5e5e5',
|
|
300: '#d4d4d4',
|
|
400: '#a3a3a3',
|
|
500: '#737373',
|
|
600: '#525252',
|
|
700: '#404040',
|
|
800: '#262626',
|
|
900: '#171717',
|
|
950: '#0a0a0a',
|
|
},
|
|
|
|
// Status colors
|
|
success: {
|
|
50: '#f0fdf4',
|
|
100: '#dcfce7',
|
|
500: '#22c55e',
|
|
600: '#16a34a',
|
|
700: '#15803d',
|
|
900: '#14532d',
|
|
},
|
|
|
|
error: {
|
|
50: '#fef2f2',
|
|
100: '#fee2e2',
|
|
500: '#ef4444',
|
|
600: '#dc2626',
|
|
700: '#b91c1c',
|
|
900: '#7f1d1d',
|
|
},
|
|
|
|
warning: {
|
|
50: '#fffbeb',
|
|
100: '#fef3c7',
|
|
500: '#f59e0b',
|
|
600: '#d97706',
|
|
700: '#b45309',
|
|
900: '#78350f',
|
|
},
|
|
|
|
info: {
|
|
50: '#eff6ff',
|
|
100: '#dbeafe',
|
|
500: '#3b82f6',
|
|
600: '#2563eb',
|
|
700: '#1d4ed8',
|
|
900: '#1e3a8a',
|
|
},
|
|
},
|
|
|
|
// Semantic color tokens
|
|
semantic: {
|
|
light: {
|
|
background: '#ffffff',
|
|
foreground: '#0a0a0a',
|
|
card: '#ffffff',
|
|
cardForeground: '#0a0a0a',
|
|
popover: '#ffffff',
|
|
popoverForeground: '#0a0a0a',
|
|
primary: '#22c55e',
|
|
primaryForeground: '#ffffff',
|
|
secondary: '#f5f5f5',
|
|
secondaryForeground: '#0a0a0a',
|
|
muted: '#f5f5f5',
|
|
mutedForeground: '#737373',
|
|
accent: '#f5f5f5',
|
|
accentForeground: '#0a0a0a',
|
|
destructive: '#ef4444',
|
|
destructiveForeground: '#ffffff',
|
|
border: '#e5e5e5',
|
|
input: '#e5e5e5',
|
|
ring: '#22c55e',
|
|
},
|
|
|
|
dark: {
|
|
background: '#0a0a0a',
|
|
foreground: '#fafafa',
|
|
card: '#171717',
|
|
cardForeground: '#fafafa',
|
|
popover: '#171717',
|
|
popoverForeground: '#fafafa',
|
|
primary: '#22c55e',
|
|
primaryForeground: '#0a0a0a',
|
|
secondary: '#262626',
|
|
secondaryForeground: '#fafafa',
|
|
muted: '#262626',
|
|
mutedForeground: '#a3a3a3',
|
|
accent: '#262626',
|
|
accentForeground: '#fafafa',
|
|
destructive: '#ef4444',
|
|
destructiveForeground: '#fafafa',
|
|
border: '#262626',
|
|
input: '#262626',
|
|
ring: '#22c55e',
|
|
},
|
|
},
|
|
|
|
// Typography
|
|
typography: {
|
|
fontFamily: {
|
|
sans: ['Vazirmatn', 'Inter', 'ui-sans-serif', 'system-ui', 'sans-serif'],
|
|
mono: ['ui-monospace', 'SFMono-Regular', 'Consolas', 'monospace'],
|
|
},
|
|
|
|
fontSize: {
|
|
xs: '0.75rem',
|
|
sm: '0.875rem',
|
|
base: '1rem',
|
|
lg: '1.125rem',
|
|
xl: '1.25rem',
|
|
'2xl': '1.5rem',
|
|
'3xl': '1.875rem',
|
|
'4xl': '2.25rem',
|
|
'5xl': '3rem',
|
|
},
|
|
|
|
fontWeight: {
|
|
light: '300',
|
|
normal: '400',
|
|
medium: '500',
|
|
semibold: '600',
|
|
bold: '700',
|
|
extrabold: '800',
|
|
},
|
|
},
|
|
|
|
// Spacing
|
|
spacing: {
|
|
0: '0px',
|
|
1: '0.25rem',
|
|
2: '0.5rem',
|
|
3: '0.75rem',
|
|
4: '1rem',
|
|
5: '1.25rem',
|
|
6: '1.5rem',
|
|
8: '2rem',
|
|
10: '2.5rem',
|
|
12: '3rem',
|
|
16: '4rem',
|
|
20: '5rem',
|
|
24: '6rem',
|
|
},
|
|
|
|
// Border radius
|
|
borderRadius: {
|
|
none: '0px',
|
|
sm: '0.125rem',
|
|
base: '0.25rem',
|
|
md: '0.375rem',
|
|
lg: '0.5rem',
|
|
xl: '0.75rem',
|
|
'2xl': '1rem',
|
|
full: '9999px',
|
|
},
|
|
|
|
// Shadows
|
|
boxShadow: {
|
|
sm: '0 1px 2px 0 rgb(0 0 0 / 0.05)',
|
|
base: '0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)',
|
|
md: '0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)',
|
|
lg: '0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)',
|
|
xl: '0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)',
|
|
none: '0 0 #0000',
|
|
},
|
|
};
|
|
|
|
// CSS custom properties generator
|
|
export const generateCSSVariables = (theme: 'light' | 'dark' = 'light') => {
|
|
const semanticColors = themeConfig.semantic[theme];
|
|
|
|
const cssVars: Record<string, string> = {};
|
|
|
|
// Generate semantic color variables
|
|
Object.entries(semanticColors).forEach(([key, value]) => {
|
|
cssVars[`--color-${key.replace(/([A-Z])/g, '-$1').toLowerCase()}`] = value;
|
|
});
|
|
|
|
// Generate primary color scale
|
|
Object.entries(themeConfig.colors.primary).forEach(([key, value]) => {
|
|
cssVars[`--color-primary-${key}`] = value;
|
|
});
|
|
|
|
// Generate secondary color scale
|
|
Object.entries(themeConfig.colors.secondary).forEach(([key, value]) => {
|
|
cssVars[`--color-secondary-${key}`] = value;
|
|
});
|
|
|
|
// Generate neutral color scale
|
|
Object.entries(themeConfig.colors.neutral).forEach(([key, value]) => {
|
|
cssVars[`--color-neutral-${key}`] = value;
|
|
});
|
|
|
|
// Generate status colors
|
|
['success', 'error', 'warning', 'info'].forEach(status => {
|
|
Object.entries(themeConfig.colors[status as keyof typeof themeConfig.colors]).forEach(([key, value]) => {
|
|
cssVars[`--color-${status}-${key}`] = value;
|
|
});
|
|
});
|
|
|
|
// Generate spacing variables
|
|
Object.entries(themeConfig.spacing).forEach(([key, value]) => {
|
|
cssVars[`--spacing-${key}`] = value;
|
|
});
|
|
|
|
// Generate border radius variables
|
|
Object.entries(themeConfig.borderRadius).forEach(([key, value]) => {
|
|
cssVars[`--radius-${key}`] = value;
|
|
});
|
|
|
|
return cssVars;
|
|
};
|
|
|
|
// Theme utilities
|
|
export const theme = {
|
|
// Get color with opacity
|
|
color: (colorPath: string, opacity?: number) => {
|
|
const baseColor = `var(--color-${colorPath.replace('.', '-')})`;
|
|
if (opacity !== undefined) {
|
|
return `oklch(from ${baseColor} l c h / ${opacity})`;
|
|
}
|
|
return baseColor;
|
|
},
|
|
|
|
// Get spacing value
|
|
spacing: (size: keyof typeof themeConfig.spacing) => {
|
|
return `var(--spacing-${size})`;
|
|
},
|
|
|
|
// Get border radius
|
|
radius: (size: keyof typeof themeConfig.borderRadius) => {
|
|
return `var(--radius-${size})`;
|
|
},
|
|
|
|
// Quick color access
|
|
colors: {
|
|
primary: (shade: keyof typeof themeConfig.colors.primary = '500') =>
|
|
`var(--color-primary-${shade})`,
|
|
secondary: (shade: keyof typeof themeConfig.colors.secondary = '500') =>
|
|
`var(--color-secondary-${shade})`,
|
|
neutral: (shade: keyof typeof themeConfig.colors.neutral = '500') =>
|
|
`var(--color-neutral-${shade})`,
|
|
success: (shade: keyof typeof themeConfig.colors.success = '500') =>
|
|
`var(--color-success-${shade})`,
|
|
error: (shade: keyof typeof themeConfig.colors.error = '500') =>
|
|
`var(--color-error-${shade})`,
|
|
warning: (shade: keyof typeof themeConfig.colors.warning = '500') =>
|
|
`var(--color-warning-${shade})`,
|
|
info: (shade: keyof typeof themeConfig.colors.info = '500') =>
|
|
`var(--color-info-${shade})`,
|
|
},
|
|
};
|
|
|
|
// Export individual color palettes for easy access
|
|
export const { colors, typography, spacing, borderRadius, boxShadow } = themeConfig;
|
|
export default themeConfig;
|