Files
igny8/frontend/src/styles/cms/typography.ts
2025-11-18 06:36:56 +05:00

182 lines
4.3 KiB
TypeScript

/**
* Typography System
* Phase 7: CMS Styling System
* Typography scale, font families, and text styles
*/
export interface TypographyScale {
xs: string;
sm: string;
base: string;
lg: string;
xl: string;
'2xl': string;
'3xl': string;
'4xl': string;
'5xl': string;
'6xl': string;
}
export interface TypographyConfig {
fontFamilies: {
sans: string[];
serif: string[];
mono: string[];
display: string[];
};
fontSizes: TypographyScale;
lineHeights: TypographyScale;
fontWeights: {
light: number;
normal: number;
medium: number;
semibold: number;
bold: number;
extrabold: number;
};
letterSpacing: {
tighter: string;
tight: string;
normal: string;
wide: string;
wider: string;
widest: string;
};
}
export const TYPOGRAPHY_CONFIG: TypographyConfig = {
fontFamilies: {
sans: ['Inter', 'system-ui', '-apple-system', 'BlinkMacSystemFont', 'Segoe UI', 'Roboto', 'sans-serif'],
serif: ['Georgia', 'Cambria', 'Times New Roman', 'Times', 'serif'],
mono: ['Menlo', 'Monaco', 'Consolas', 'Liberation Mono', 'Courier New', 'monospace'],
display: ['Inter', 'system-ui', 'sans-serif'],
},
fontSizes: {
xs: '0.75rem', // 12px
sm: '0.875rem', // 14px
base: '1rem', // 16px
lg: '1.125rem', // 18px
xl: '1.25rem', // 20px
'2xl': '1.5rem', // 24px
'3xl': '1.875rem', // 30px
'4xl': '2.25rem', // 36px
'5xl': '3rem', // 48px
'6xl': '3.75rem', // 60px
},
lineHeights: {
xs: '1rem',
sm: '1.25rem',
base: '1.5rem',
lg: '1.75rem',
xl: '2rem',
'2xl': '2.25rem',
'3xl': '2.5rem',
'4xl': '2.75rem',
'5xl': '1',
'6xl': '1',
},
fontWeights: {
light: 300,
normal: 400,
medium: 500,
semibold: 600,
bold: 700,
extrabold: 800,
},
letterSpacing: {
tighter: '-0.05em',
tight: '-0.025em',
normal: '0em',
wide: '0.025em',
wider: '0.05em',
widest: '0.1em',
},
};
export interface TypographyPreset {
id: string;
name: string;
description: string;
headingFont: string;
bodyFont: string;
baseSize: string;
lineHeight: string;
}
export const TYPOGRAPHY_PRESETS: TypographyPreset[] = [
{
id: 'modern',
name: 'Modern Sans',
description: 'Clean, modern sans-serif typography',
headingFont: 'Inter, system-ui, sans-serif',
bodyFont: 'Inter, system-ui, sans-serif',
baseSize: '16px',
lineHeight: '1.6',
},
{
id: 'classic',
name: 'Classic Serif',
description: 'Traditional serif typography',
headingFont: 'Georgia, serif',
bodyFont: 'Georgia, serif',
baseSize: '18px',
lineHeight: '1.7',
},
{
id: 'editorial',
name: 'Editorial',
description: 'Magazine-style typography',
headingFont: 'Playfair Display, serif',
bodyFont: 'Lora, serif',
baseSize: '17px',
lineHeight: '1.75',
},
{
id: 'minimal',
name: 'Minimal',
description: 'Minimalist typography with high readability',
headingFont: 'Helvetica, Arial, sans-serif',
bodyFont: 'Helvetica, Arial, sans-serif',
baseSize: '16px',
lineHeight: '1.8',
},
{
id: 'tech',
name: 'Tech',
description: 'Modern tech typography',
headingFont: 'SF Pro Display, system-ui, sans-serif',
bodyFont: 'SF Pro Text, system-ui, sans-serif',
baseSize: '16px',
lineHeight: '1.6',
},
];
export function getTypographyPreset(presetId: string): TypographyPreset | undefined {
return TYPOGRAPHY_PRESETS.find((preset) => preset.id === presetId);
}
export function generateTypographyCSS(config: TypographyConfig, preset?: TypographyPreset): string {
const headingFont = preset?.headingFont || config.fontFamilies.display.join(', ');
const bodyFont = preset?.bodyFont || config.fontFamilies.sans.join(', ');
const baseSize = preset?.baseSize || config.fontSizes.base;
const lineHeight = preset?.lineHeight || config.lineHeights.base;
return `
:root {
--font-heading: ${headingFont};
--font-body: ${bodyFont};
--font-size-base: ${baseSize};
--line-height-base: ${lineHeight};
${Object.entries(config.fontSizes)
.map(([key, value]) => `--font-size-${key}: ${value};`)
.join('\n ')}
${Object.entries(config.fontWeights)
.map(([key, value]) => `--font-weight-${key}: ${value};`)
.join('\n ')}
}
`.trim();
}