EDMS/composables/useDesignSystem.js
2025-06-05 14:57:08 +08:00

320 lines
9.0 KiB
JavaScript

// Design System Composable for DMS
// Provides consistent design tokens, spacing, animations, and patterns
export const useDesignSystem = () => {
// Design Tokens
const tokens = {
// Spacing System (8px base grid)
spacing: {
xs: '0.25rem', // 4px
sm: '0.5rem', // 8px
md: '0.75rem', // 12px
lg: '1rem', // 16px
xl: '1.5rem', // 24px
'2xl': '2rem', // 32px
'3xl': '3rem', // 48px
'4xl': '4rem', // 64px
},
// Typography Scale
typography: {
sizes: {
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
},
weights: {
light: '300',
normal: '400',
medium: '500',
semibold: '600',
bold: '700',
extrabold: '800',
},
lineHeights: {
tight: '1.25',
normal: '1.5',
relaxed: '1.75',
}
},
// Border Radius
radius: {
none: '0',
sm: '0.25rem', // 4px
md: '0.375rem', // 6px
lg: '0.5rem', // 8px
xl: '0.75rem', // 12px
'2xl': '1rem', // 16px
full: '9999px',
},
// Shadows
shadows: {
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)',
inner: 'inset 0 2px 4px 0 rgb(0 0 0 / 0.05)',
},
// Z-Index Scale
zIndex: {
base: 0,
dropdown: 1000,
sticky: 1020,
fixed: 1030,
modal: 1040,
popover: 1050,
tooltip: 1060,
toast: 1070,
}
};
// Animation Presets
const animations = {
// Duration
duration: {
fast: '150ms',
normal: '250ms',
slow: '350ms',
},
// Easing
easing: {
linear: 'linear',
ease: 'ease',
'ease-in': 'ease-in',
'ease-out': 'ease-out',
'ease-in-out': 'ease-in-out',
spring: 'cubic-bezier(0.175, 0.885, 0.32, 1.275)',
},
// Common Animation Classes
transitions: {
fadeIn: {
enter: 'transition-opacity duration-250 ease-in-out',
enterFrom: 'opacity-0',
enterTo: 'opacity-100',
leave: 'transition-opacity duration-250 ease-in-out',
leaveFrom: 'opacity-100',
leaveTo: 'opacity-0',
},
slideDown: {
enter: 'transition-all duration-250 ease-in-out',
enterFrom: 'opacity-0 transform -translate-y-2',
enterTo: 'opacity-100 transform translate-y-0',
leave: 'transition-all duration-250 ease-in-out',
leaveFrom: 'opacity-100 transform translate-y-0',
leaveTo: 'opacity-0 transform -translate-y-2',
},
scaleIn: {
enter: 'transition-all duration-250 ease-in-out',
enterFrom: 'opacity-0 transform scale-95',
enterTo: 'opacity-100 transform scale-100',
leave: 'transition-all duration-250 ease-in-out',
leaveFrom: 'opacity-100 transform scale-100',
leaveTo: 'opacity-0 transform scale-95',
}
}
};
// Component Size Variants
const sizes = {
button: {
sm: 'px-3 py-1.5 text-sm',
md: 'px-4 py-2 text-sm',
lg: 'px-6 py-3 text-base',
xl: 'px-8 py-4 text-lg',
},
input: {
sm: 'px-3 py-1.5 text-sm',
md: 'px-3 py-2 text-sm',
lg: 'px-4 py-3 text-base',
},
modal: {
sm: 'max-w-sm',
md: 'max-w-md',
lg: 'max-w-lg',
xl: 'max-w-xl',
'2xl': 'max-w-2xl',
'3xl': 'max-w-3xl',
'4xl': 'max-w-4xl',
'5xl': 'max-w-5xl',
'6xl': 'max-w-6xl',
full: 'max-w-full',
}
};
// Status Colors with Semantic Meaning
const statusColors = {
// Success states
success: {
bg: 'bg-green-50 dark:bg-green-900/10',
border: 'border-green-200 dark:border-green-800',
text: 'text-green-800 dark:text-green-200',
icon: 'text-green-600 dark:text-green-400',
},
// Warning states
warning: {
bg: 'bg-yellow-50 dark:bg-yellow-900/10',
border: 'border-yellow-200 dark:border-yellow-800',
text: 'text-yellow-800 dark:text-yellow-200',
icon: 'text-yellow-600 dark:text-yellow-400',
},
// Error states
error: {
bg: 'bg-red-50 dark:bg-red-900/10',
border: 'border-red-200 dark:border-red-800',
text: 'text-red-800 dark:text-red-200',
icon: 'text-red-600 dark:text-red-400',
},
// Info states
info: {
bg: 'bg-blue-50 dark:bg-blue-900/10',
border: 'border-blue-200 dark:border-blue-800',
text: 'text-blue-800 dark:text-blue-200',
icon: 'text-blue-600 dark:text-blue-400',
},
// Neutral states
neutral: {
bg: 'bg-gray-50 dark:bg-gray-800',
border: 'border-gray-200 dark:border-gray-600',
text: 'text-gray-800 dark:text-gray-200',
icon: 'text-gray-600 dark:text-gray-400',
}
};
// Interactive States
const states = {
loading: {
disabled: 'disabled:opacity-50 disabled:cursor-not-allowed',
spinner: 'animate-spin rounded-full border-2 border-current border-t-transparent',
},
hover: {
lift: 'hover:transform hover:-translate-y-0.5 hover:shadow-lg transition-all duration-200',
glow: 'hover:shadow-lg hover:shadow-current/25 transition-all duration-200',
scale: 'hover:scale-105 transition-transform duration-200',
},
focus: {
ring: 'focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary',
visible: 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2',
}
};
// Layout Patterns
const layouts = {
stack: 'flex flex-col space-y-4',
hstack: 'flex items-center space-x-4',
center: 'flex items-center justify-center',
between: 'flex items-center justify-between',
grid: {
cols1: 'grid grid-cols-1 gap-4',
cols2: 'grid grid-cols-1 md:grid-cols-2 gap-4',
cols3: 'grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4',
cols4: 'grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4',
}
};
// Utility Functions
const utils = {
// Generate consistent component classes
composeClasses: (...classes) => {
return classes.filter(Boolean).join(' ');
},
// Get status variant classes
getStatusClasses: (status, element = 'bg') => {
return statusColors[status]?.[element] || statusColors.neutral[element];
},
// Get size classes for components
getSizeClasses: (component, size = 'md') => {
return sizes[component]?.[size] || sizes[component]?.md || '';
},
// Generate animation classes
getAnimationClasses: (type = 'fadeIn') => {
return animations.transitions[type] || animations.transitions.fadeIn;
},
// Create CSS custom properties
createCSSVars: (vars) => {
return Object.entries(vars).reduce((acc, [key, value]) => {
acc[`--${key}`] = value;
return acc;
}, {});
},
// Responsive breakpoint utilities
responsive: {
sm: '640px',
md: '768px',
lg: '1024px',
xl: '1280px',
'2xl': '1536px',
}
};
// DMS-Specific Patterns
const dmsPatterns = {
// File type icons mapping
fileIcons: {
pdf: 'mdi:file-pdf-box',
doc: 'mdi:file-word-box',
docx: 'mdi:file-word-box',
xls: 'mdi:file-excel-box',
xlsx: 'mdi:file-excel-box',
ppt: 'mdi:file-powerpoint-box',
pptx: 'mdi:file-powerpoint-box',
jpg: 'mdi:file-image-box',
jpeg: 'mdi:file-image-box',
png: 'mdi:file-image-box',
gif: 'mdi:file-image-box',
txt: 'mdi:file-document-box',
default: 'mdi:file-document-box',
},
// Status badges for documents
documentStatus: {
draft: { color: 'gray', icon: 'mdi:file-edit' },
review: { color: 'yellow', icon: 'mdi:file-eye' },
approved: { color: 'green', icon: 'mdi:file-check' },
archived: { color: 'blue', icon: 'mdi:file-cabinet' },
rejected: { color: 'red', icon: 'mdi:file-cancel' },
},
// Permission levels
permissions: {
read: { label: 'View Only', color: 'blue', icon: 'mdi:eye' },
write: { label: 'Edit', color: 'green', icon: 'mdi:pencil' },
delete: { label: 'Delete', color: 'red', icon: 'mdi:delete' },
admin: { label: 'Admin', color: 'purple', icon: 'mdi:shield-account' },
},
// Common DMS layouts
layouts: {
sidebar: 'flex h-screen bg-gray-50 dark:bg-gray-900',
content: 'flex-1 flex flex-col overflow-hidden',
panel: 'w-64 flex-shrink-0 border-r border-gray-200 dark:border-gray-700',
main: 'flex-1 p-6 overflow-auto',
}
};
return {
tokens,
animations,
sizes,
statusColors,
states,
layouts,
utils,
dmsPatterns,
};
};