// 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, }; };