468 lines
12 KiB
JavaScript
468 lines
12 KiB
JavaScript
/**
|
|
* Design Token System for Oil Customer Gateway
|
|
*
|
|
* This file centralizes all design values to ensure consistency across the app.
|
|
* Import and use these tokens instead of hardcoding values.
|
|
*
|
|
* Usage:
|
|
* import { colors, spacing, fontSize, ... } from '../theme';
|
|
* style={{ color: colors.primary, padding: spacing.md }}
|
|
*/
|
|
|
|
// =============================================================================
|
|
// COLORS
|
|
// =============================================================================
|
|
|
|
export const colors = {
|
|
// Brand Colors
|
|
primary: '#14368f', // Oil blue - main brand color
|
|
secondary: '#ff6600', // Oil orange - accent/CTA color
|
|
|
|
// Neutral Colors
|
|
white: '#ffffff',
|
|
black: '#000000',
|
|
gray: {
|
|
50: '#fafafa',
|
|
100: '#f5f5f5', // Card backgrounds, subtle backgrounds
|
|
200: '#e8e8e8', // Borders, dividers
|
|
300: '#d9d9d9', // Input borders
|
|
400: '#bfbfbf',
|
|
500: '#8c8c8c',
|
|
600: '#666666', // Hint text, secondary text
|
|
700: '#333837', // Oil gray - dark text
|
|
800: '#262626',
|
|
900: '#1f1f1f',
|
|
},
|
|
|
|
// Semantic Colors
|
|
success: '#52c41a',
|
|
successLight: '#d4edda', // Light green for waiting delivery
|
|
warning: '#faad14',
|
|
warningLight: '#fff7e6', // Warning card background
|
|
warningBorder: '#ffcc02',
|
|
error: '#ff4d4f',
|
|
info: '#1890ff', // Links, info elements
|
|
|
|
// Status Colors
|
|
gold: '#ffd700', // Out for delivery highlight
|
|
goldGlow: 'rgba(255, 215, 0, 0.5)',
|
|
|
|
// Background Colors
|
|
background: {
|
|
page: '#ffffff',
|
|
card: '#f5f5f5',
|
|
overlay: 'rgba(0, 0, 0, 0.45)',
|
|
},
|
|
|
|
// Text Colors
|
|
text: {
|
|
primary: 'rgba(0, 0, 0, 0.85)',
|
|
secondary: 'rgba(0, 0, 0, 0.65)',
|
|
hint: '#666666',
|
|
inverse: '#ffffff',
|
|
link: '#1890ff',
|
|
},
|
|
};
|
|
|
|
// =============================================================================
|
|
// SPACING
|
|
// =============================================================================
|
|
|
|
export const spacing = {
|
|
xxs: 4,
|
|
xs: 8,
|
|
sm: 12,
|
|
md: 16,
|
|
lg: 24,
|
|
xl: 32,
|
|
xxl: 48,
|
|
|
|
// Specific use cases
|
|
gutter: {
|
|
xs: 8, // Mobile gutter
|
|
md: 16, // Default gutter
|
|
lg: 24, // Large screens
|
|
},
|
|
|
|
// Content padding
|
|
content: {
|
|
mobile: 8,
|
|
tablet: 16,
|
|
desktop: 50,
|
|
},
|
|
|
|
// Card/section padding
|
|
card: {
|
|
xs: 12,
|
|
sm: 16,
|
|
md: 24,
|
|
},
|
|
};
|
|
|
|
// =============================================================================
|
|
// TYPOGRAPHY
|
|
// =============================================================================
|
|
|
|
export const fontSize = {
|
|
xs: 12,
|
|
sm: 14,
|
|
base: 16,
|
|
lg: 18,
|
|
xl: 20,
|
|
'2xl': 24,
|
|
'3xl': 32,
|
|
};
|
|
|
|
export const fontWeight = {
|
|
normal: 400,
|
|
medium: 500,
|
|
semibold: 600,
|
|
bold: 700,
|
|
};
|
|
|
|
export const lineHeight = {
|
|
tight: 1.25,
|
|
normal: 1.5,
|
|
relaxed: 1.6,
|
|
loose: 2,
|
|
};
|
|
|
|
// =============================================================================
|
|
// BORDERS
|
|
// =============================================================================
|
|
|
|
export const borderRadius = {
|
|
sm: 4,
|
|
md: 6,
|
|
lg: 8,
|
|
xl: 12,
|
|
full: 9999,
|
|
};
|
|
|
|
export const borderWidth = {
|
|
default: 1,
|
|
thick: 2,
|
|
};
|
|
|
|
// =============================================================================
|
|
// SHADOWS
|
|
// =============================================================================
|
|
|
|
export const shadows = {
|
|
sm: '0 1px 2px 0 rgba(0, 0, 0, 0.05)',
|
|
md: '0 4px 6px -1px rgba(0, 0, 0, 0.1)',
|
|
lg: '0 10px 15px -3px rgba(0, 0, 0, 0.1)',
|
|
glow: {
|
|
gold: '0 0 10px rgba(255, 215, 0, 0.5)',
|
|
},
|
|
};
|
|
|
|
// =============================================================================
|
|
// BREAKPOINTS
|
|
// =============================================================================
|
|
|
|
export const breakpoints = {
|
|
xs: 480,
|
|
sm: 576,
|
|
md: 768,
|
|
lg: 992,
|
|
xl: 1200,
|
|
xxl: 1600,
|
|
};
|
|
|
|
// =============================================================================
|
|
// TRANSITIONS
|
|
// =============================================================================
|
|
|
|
export const transitions = {
|
|
fast: '0.15s ease',
|
|
normal: '0.3s ease',
|
|
slow: '0.5s ease',
|
|
};
|
|
|
|
// =============================================================================
|
|
// Z-INDEX
|
|
// =============================================================================
|
|
|
|
export const zIndex = {
|
|
dropdown: 1000,
|
|
sticky: 1020,
|
|
fixed: 1030,
|
|
modal: 1040,
|
|
popover: 1050,
|
|
tooltip: 1060,
|
|
};
|
|
|
|
// =============================================================================
|
|
// COMPONENT-SPECIFIC TOKENS
|
|
// =============================================================================
|
|
|
|
export const components = {
|
|
// Header
|
|
header: {
|
|
height: 64,
|
|
background: colors.primary,
|
|
},
|
|
|
|
// Logo
|
|
logo: {
|
|
height: 32,
|
|
},
|
|
|
|
// Buttons
|
|
button: {
|
|
height: {
|
|
sm: 32,
|
|
default: 40,
|
|
lg: 48,
|
|
xl: 60,
|
|
},
|
|
fontSize: {
|
|
sm: fontSize.sm,
|
|
default: fontSize.base,
|
|
lg: fontSize.lg,
|
|
},
|
|
},
|
|
|
|
// Cards
|
|
card: {
|
|
background: colors.background.card,
|
|
border: `1px solid ${colors.gray[200]}`,
|
|
borderRadius: borderRadius.lg,
|
|
},
|
|
|
|
// Tables
|
|
table: {
|
|
scrollHeight: 400,
|
|
},
|
|
|
|
// Forms
|
|
form: {
|
|
maxWidth: 400,
|
|
labelFontSize: fontSize.sm,
|
|
},
|
|
|
|
// Images
|
|
image: {
|
|
thumbnail: {
|
|
mobile: 120,
|
|
desktop: 100,
|
|
},
|
|
preview: 150,
|
|
},
|
|
};
|
|
|
|
// =============================================================================
|
|
// ANT DESIGN THEME CONFIG
|
|
// =============================================================================
|
|
|
|
/**
|
|
* Use this with Ant Design's ConfigProvider to apply consistent theming
|
|
*
|
|
* Usage:
|
|
* import { antdTheme } from './theme';
|
|
* <ConfigProvider theme={antdTheme}>
|
|
* <App />
|
|
* </ConfigProvider>
|
|
*/
|
|
export const antdTheme = {
|
|
token: {
|
|
colorPrimary: colors.primary,
|
|
colorLink: colors.text.link,
|
|
colorSuccess: colors.success,
|
|
colorWarning: colors.warning,
|
|
colorError: colors.error,
|
|
colorInfo: colors.info,
|
|
|
|
borderRadius: borderRadius.md,
|
|
|
|
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',
|
|
fontSize: fontSize.base,
|
|
|
|
colorBgContainer: colors.white,
|
|
colorBgLayout: colors.gray[100],
|
|
|
|
paddingXS: spacing.xs,
|
|
paddingSM: spacing.sm,
|
|
padding: spacing.md,
|
|
paddingLG: spacing.lg,
|
|
paddingXL: spacing.xl,
|
|
},
|
|
components: {
|
|
Button: {
|
|
colorPrimaryHover: '#1e4db8',
|
|
borderRadius: borderRadius.md,
|
|
},
|
|
Card: {
|
|
colorBgContainer: colors.gray[100],
|
|
},
|
|
},
|
|
};
|
|
|
|
// =============================================================================
|
|
// CSS CUSTOM PROPERTIES
|
|
// =============================================================================
|
|
|
|
/**
|
|
* Injects CSS custom properties (variables) into the document root.
|
|
* Call this once at app initialization.
|
|
*
|
|
* Usage in CSS:
|
|
* color: var(--color-primary);
|
|
* padding: var(--spacing-md);
|
|
*/
|
|
export const injectCSSVariables = () => {
|
|
const root = document.documentElement;
|
|
|
|
// Colors
|
|
root.style.setProperty('--color-primary', colors.primary);
|
|
root.style.setProperty('--color-secondary', colors.secondary);
|
|
root.style.setProperty('--color-white', colors.white);
|
|
root.style.setProperty('--color-success', colors.success);
|
|
root.style.setProperty('--color-success-light', colors.successLight);
|
|
root.style.setProperty('--color-warning', colors.warning);
|
|
root.style.setProperty('--color-warning-light', colors.warningLight);
|
|
root.style.setProperty('--color-warning-border', colors.warningBorder);
|
|
root.style.setProperty('--color-error', colors.error);
|
|
root.style.setProperty('--color-info', colors.info);
|
|
root.style.setProperty('--color-gold', colors.gold);
|
|
root.style.setProperty('--color-text-primary', colors.text.primary);
|
|
root.style.setProperty('--color-text-secondary', colors.text.secondary);
|
|
root.style.setProperty('--color-text-hint', colors.text.hint);
|
|
root.style.setProperty('--color-text-inverse', colors.text.inverse);
|
|
root.style.setProperty('--color-text-link', colors.text.link);
|
|
root.style.setProperty('--color-bg-card', colors.background.card);
|
|
root.style.setProperty('--color-border', colors.gray[200]);
|
|
root.style.setProperty('--color-border-input', colors.gray[300]);
|
|
|
|
// Grays
|
|
Object.entries(colors.gray).forEach(([key, value]) => {
|
|
root.style.setProperty(`--color-gray-${key}`, value);
|
|
});
|
|
|
|
// Spacing
|
|
root.style.setProperty('--spacing-xxs', `${spacing.xxs}px`);
|
|
root.style.setProperty('--spacing-xs', `${spacing.xs}px`);
|
|
root.style.setProperty('--spacing-sm', `${spacing.sm}px`);
|
|
root.style.setProperty('--spacing-md', `${spacing.md}px`);
|
|
root.style.setProperty('--spacing-lg', `${spacing.lg}px`);
|
|
root.style.setProperty('--spacing-xl', `${spacing.xl}px`);
|
|
root.style.setProperty('--spacing-xxl', `${spacing.xxl}px`);
|
|
|
|
// Font sizes
|
|
root.style.setProperty('--font-size-xs', `${fontSize.xs}px`);
|
|
root.style.setProperty('--font-size-sm', `${fontSize.sm}px`);
|
|
root.style.setProperty('--font-size-base', `${fontSize.base}px`);
|
|
root.style.setProperty('--font-size-lg', `${fontSize.lg}px`);
|
|
root.style.setProperty('--font-size-xl', `${fontSize.xl}px`);
|
|
root.style.setProperty('--font-size-2xl', `${fontSize['2xl']}px`);
|
|
root.style.setProperty('--font-size-3xl', `${fontSize['3xl']}px`);
|
|
|
|
// Border radius
|
|
root.style.setProperty('--radius-sm', `${borderRadius.sm}px`);
|
|
root.style.setProperty('--radius-md', `${borderRadius.md}px`);
|
|
root.style.setProperty('--radius-lg', `${borderRadius.lg}px`);
|
|
root.style.setProperty('--radius-xl', `${borderRadius.xl}px`);
|
|
|
|
// Shadows
|
|
root.style.setProperty('--shadow-sm', shadows.sm);
|
|
root.style.setProperty('--shadow-md', shadows.md);
|
|
root.style.setProperty('--shadow-lg', shadows.lg);
|
|
root.style.setProperty('--shadow-glow-gold', shadows.glow.gold);
|
|
|
|
// Transitions
|
|
root.style.setProperty('--transition-fast', transitions.fast);
|
|
root.style.setProperty('--transition-normal', transitions.normal);
|
|
root.style.setProperty('--transition-slow', transitions.slow);
|
|
};
|
|
|
|
// =============================================================================
|
|
// STYLE UTILITIES
|
|
// =============================================================================
|
|
|
|
/**
|
|
* Pre-built button styles for common use cases.
|
|
* Import and spread these in your style prop.
|
|
*
|
|
* Usage:
|
|
* import { buttonStyles } from '../theme';
|
|
* <Button style={buttonStyles.ctaLarge}>Order Now</Button>
|
|
*/
|
|
export const buttonStyles = {
|
|
// Primary CTA button (orange, large)
|
|
ctaLarge: {
|
|
backgroundColor: colors.secondary,
|
|
borderColor: colors.secondary,
|
|
height: 60,
|
|
fontSize: fontSize.lg,
|
|
minWidth: 150,
|
|
},
|
|
// Primary CTA button for mobile
|
|
ctaMobile: {
|
|
backgroundColor: colors.secondary,
|
|
borderColor: colors.secondary,
|
|
height: 48,
|
|
fontSize: fontSize.base,
|
|
width: '100%',
|
|
},
|
|
// Standard primary button
|
|
primary: {
|
|
backgroundColor: colors.primary,
|
|
borderColor: colors.primary,
|
|
},
|
|
// Text button on dark background
|
|
headerText: {
|
|
color: colors.white,
|
|
},
|
|
};
|
|
|
|
/**
|
|
* Common style patterns for reuse.
|
|
*/
|
|
export const commonStyles = {
|
|
// Card with gray background
|
|
cardGray: {
|
|
backgroundColor: colors.gray[100],
|
|
},
|
|
// Warning/emergency card
|
|
cardWarning: {
|
|
backgroundColor: colors.warningLight,
|
|
borderColor: colors.warningBorder,
|
|
},
|
|
// Centered flex container
|
|
flexCenter: {
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
},
|
|
// Link styling
|
|
link: {
|
|
color: colors.text.link,
|
|
},
|
|
};
|
|
|
|
// =============================================================================
|
|
// DEFAULT EXPORT
|
|
// =============================================================================
|
|
|
|
const theme = {
|
|
colors,
|
|
spacing,
|
|
fontSize,
|
|
fontWeight,
|
|
lineHeight,
|
|
borderRadius,
|
|
borderWidth,
|
|
shadows,
|
|
breakpoints,
|
|
transitions,
|
|
zIndex,
|
|
components,
|
|
antdTheme,
|
|
injectCSSVariables,
|
|
buttonStyles,
|
|
commonStyles,
|
|
};
|
|
|
|
export default theme;
|