270 lines
10 KiB
TypeScript
270 lines
10 KiB
TypeScript
|
|
// =============================================================================
|
||
|
|
// Analytics Feature - UnoCSS Configuration Template
|
||
|
|
// =============================================================================
|
||
|
|
// This file demonstrates layered override system for feature-specific styles.
|
||
|
|
// It will be merged with base UnoCSS config when analytics feature is enabled.
|
||
|
|
// Layer: Feature > Template > Framework
|
||
|
|
|
||
|
|
import { defineConfig } from 'unocss'
|
||
|
|
|
||
|
|
export default defineConfig({
|
||
|
|
// Analytics-specific theme extensions
|
||
|
|
theme: {
|
||
|
|
colors: {
|
||
|
|
// Analytics color palette
|
||
|
|
analytics: {
|
||
|
|
primary: '#10b981', // Green for positive metrics
|
||
|
|
secondary: '#3b82f6', // Blue for neutral metrics
|
||
|
|
warning: '#f59e0b', // Amber for warnings
|
||
|
|
danger: '#ef4444', // Red for errors/negative metrics
|
||
|
|
info: '#06b6d4', // Cyan for informational metrics
|
||
|
|
success: '#22c55e', // Light green for success states
|
||
|
|
muted: '#6b7280', // Gray for disabled/muted elements
|
||
|
|
},
|
||
|
|
// Chart specific colors
|
||
|
|
chart: {
|
||
|
|
line1: '#8b5cf6', // Purple
|
||
|
|
line2: '#06b6d4', // Cyan
|
||
|
|
line3: '#f59e0b', // Amber
|
||
|
|
line4: '#ef4444', // Red
|
||
|
|
line5: '#22c55e', // Green
|
||
|
|
area: '#e5e7eb20', // Light gray with transparency
|
||
|
|
grid: '#f3f4f6', // Very light gray
|
||
|
|
},
|
||
|
|
// Status indicators
|
||
|
|
status: {
|
||
|
|
online: '#22c55e', // Green
|
||
|
|
offline: '#ef4444', // Red
|
||
|
|
pending: '#f59e0b', // Amber
|
||
|
|
processing: '#3b82f6', // Blue
|
||
|
|
}
|
||
|
|
},
|
||
|
|
// Analytics-specific font sizes for metrics
|
||
|
|
fontSize: {
|
||
|
|
'metric-xs': '0.625rem', // 10px - small labels
|
||
|
|
'metric-sm': '0.75rem', // 12px - secondary metrics
|
||
|
|
'metric-base': '0.875rem', // 14px - base metrics
|
||
|
|
'metric-lg': '1rem', // 16px - primary metrics
|
||
|
|
'metric-xl': '1.25rem', // 20px - featured metrics
|
||
|
|
'metric-2xl': '1.5rem', // 24px - hero metrics
|
||
|
|
'metric-3xl': '2rem', // 32px - dashboard highlights
|
||
|
|
'metric-4xl': '2.5rem', // 40px - main KPIs
|
||
|
|
},
|
||
|
|
// Spacing for analytics layouts
|
||
|
|
spacing: {
|
||
|
|
'metric': '0.375rem', // 6px - metric spacing
|
||
|
|
'chart': '1rem', // 16px - chart padding
|
||
|
|
'dashboard': '1.5rem', // 24px - dashboard sections
|
||
|
|
'kpi': '2rem', // 32px - KPI spacing
|
||
|
|
},
|
||
|
|
},
|
||
|
|
|
||
|
|
// Analytics-specific utility shortcuts
|
||
|
|
shortcuts: {
|
||
|
|
// Metric display components
|
||
|
|
'metric-card': 'bg-white dark:bg-gray-800 shadow-sm border border-gray-200 dark:border-gray-700 rounded-lg p-4 hover:shadow-md transition-shadow',
|
||
|
|
'metric-card-featured': 'metric-card border-analytics-primary bg-gradient-to-br from-analytics-primary/5 to-transparent',
|
||
|
|
'metric-value': 'text-metric-2xl font-bold text-gray-900 dark:text-gray-100',
|
||
|
|
'metric-label': 'text-metric-sm font-medium text-gray-600 dark:text-gray-400 uppercase tracking-wide',
|
||
|
|
'metric-change-positive': 'text-metric-sm font-medium text-analytics-success',
|
||
|
|
'metric-change-negative': 'text-metric-sm font-medium text-analytics-danger',
|
||
|
|
'metric-change-neutral': 'text-metric-sm font-medium text-gray-500',
|
||
|
|
|
||
|
|
// Chart containers
|
||
|
|
'chart-container': 'bg-white dark:bg-gray-800 rounded-lg p-chart shadow-sm border border-gray-200 dark:border-gray-700',
|
||
|
|
'chart-header': 'flex items-center justify-between mb-4',
|
||
|
|
'chart-title': 'text-lg font-semibold text-gray-900 dark:text-gray-100',
|
||
|
|
'chart-subtitle': 'text-metric-sm text-gray-600 dark:text-gray-400',
|
||
|
|
'chart-legend': 'flex flex-wrap gap-4 text-metric-sm',
|
||
|
|
'chart-legend-item': 'flex items-center gap-1.5',
|
||
|
|
'chart-legend-dot': 'w-3 h-3 rounded-full',
|
||
|
|
|
||
|
|
// Dashboard layouts
|
||
|
|
'dashboard-grid': 'grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-dashboard',
|
||
|
|
'dashboard-section': 'space-y-dashboard',
|
||
|
|
'dashboard-header': 'flex items-center justify-between py-4 border-b border-gray-200 dark:border-gray-700',
|
||
|
|
'dashboard-title': 'text-2xl font-bold text-gray-900 dark:text-gray-100',
|
||
|
|
'dashboard-filters': 'flex flex-wrap items-center gap-2',
|
||
|
|
|
||
|
|
// Status indicators
|
||
|
|
'status-badge': 'inline-flex items-center px-2.5 py-0.5 rounded-full text-metric-xs font-medium',
|
||
|
|
'status-online': 'status-badge bg-status-online/10 text-status-online',
|
||
|
|
'status-offline': 'status-badge bg-status-offline/10 text-status-offline',
|
||
|
|
'status-pending': 'status-badge bg-status-pending/10 text-status-pending',
|
||
|
|
'status-processing': 'status-badge bg-status-processing/10 text-status-processing',
|
||
|
|
|
||
|
|
// Analytics-specific buttons
|
||
|
|
'btn-analytics': 'btn bg-analytics-primary hover:bg-analytics-primary/80 text-white',
|
||
|
|
'btn-analytics-outline': 'btn border-2 border-analytics-primary text-analytics-primary hover:bg-analytics-primary hover:text-white',
|
||
|
|
'btn-export': 'btn bg-analytics-info hover:bg-analytics-info/80 text-white',
|
||
|
|
'btn-refresh': 'btn bg-gray-100 hover:bg-gray-200 text-gray-700 dark:bg-gray-700 dark:hover:bg-gray-600 dark:text-gray-200',
|
||
|
|
|
||
|
|
// Interactive elements
|
||
|
|
'metric-hover': 'transition-all duration-200 hover:scale-105 cursor-pointer',
|
||
|
|
'chart-point': 'w-2 h-2 rounded-full transition-all hover:w-3 hover:h-3',
|
||
|
|
'tooltip-analytics': 'bg-gray-900 text-white text-metric-xs px-2 py-1 rounded shadow-lg',
|
||
|
|
|
||
|
|
// Loading states
|
||
|
|
'loading-metric': 'animate-pulse bg-gray-200 dark:bg-gray-700 rounded h-8',
|
||
|
|
'loading-chart': 'animate-pulse bg-gray-200 dark:bg-gray-700 rounded h-48',
|
||
|
|
'loading-shimmer': 'animate-pulse bg-gradient-to-r from-gray-200 via-gray-100 to-gray-200 dark:from-gray-700 dark:via-gray-600 dark:to-gray-700',
|
||
|
|
},
|
||
|
|
|
||
|
|
// Analytics-specific rules for dynamic utilities
|
||
|
|
rules: [
|
||
|
|
// Metric size rule: metric-{number}
|
||
|
|
[/^metric-(\d+)$/, ([, d]) => ({ 'font-size': `${d}px`, 'line-height': '1.2' })],
|
||
|
|
|
||
|
|
// Chart height rule: chart-h-{number}
|
||
|
|
[/^chart-h-(\d+)$/, ([, h]) => ({ height: `${h}px` })],
|
||
|
|
|
||
|
|
// Status color rule: status-{color}
|
||
|
|
[/^status-(.+)$/, ([, color]) => {
|
||
|
|
const colors: Record<string, string> = {
|
||
|
|
success: '#22c55e',
|
||
|
|
error: '#ef4444',
|
||
|
|
warning: '#f59e0b',
|
||
|
|
info: '#06b6d4',
|
||
|
|
}
|
||
|
|
return colors[color] ? { color: colors[color] } : {}
|
||
|
|
}],
|
||
|
|
|
||
|
|
// Analytics gradient rule: analytics-gradient-{direction}
|
||
|
|
[/^analytics-gradient-(.+)$/, ([, direction]) => {
|
||
|
|
const gradients: Record<string, string> = {
|
||
|
|
'success': 'linear-gradient(135deg, #22c55e 0%, #16a34a 100%)',
|
||
|
|
'warning': 'linear-gradient(135deg, #f59e0b 0%, #d97706 100%)',
|
||
|
|
'info': 'linear-gradient(135deg, #06b6d4 0%, #0891b2 100%)',
|
||
|
|
'primary': 'linear-gradient(135deg, #10b981 0%, #059669 100%)',
|
||
|
|
}
|
||
|
|
return gradients[direction] ? { 'background-image': gradients[direction] } : {}
|
||
|
|
}],
|
||
|
|
],
|
||
|
|
|
||
|
|
// Safelist for analytics classes that should always be included
|
||
|
|
safelist: [
|
||
|
|
// Ensure all status colors are included
|
||
|
|
'status-online',
|
||
|
|
'status-offline',
|
||
|
|
'status-pending',
|
||
|
|
'status-processing',
|
||
|
|
|
||
|
|
// Metric display classes
|
||
|
|
'metric-card',
|
||
|
|
'metric-value',
|
||
|
|
'metric-label',
|
||
|
|
'metric-change-positive',
|
||
|
|
'metric-change-negative',
|
||
|
|
'metric-change-neutral',
|
||
|
|
|
||
|
|
// Chart classes
|
||
|
|
'chart-container',
|
||
|
|
'chart-title',
|
||
|
|
'chart-legend',
|
||
|
|
|
||
|
|
// Dashboard layout
|
||
|
|
'dashboard-grid',
|
||
|
|
'dashboard-section',
|
||
|
|
|
||
|
|
// Dynamic classes that might be used in JavaScript
|
||
|
|
'text-analytics-primary',
|
||
|
|
'text-analytics-success',
|
||
|
|
'text-analytics-danger',
|
||
|
|
'text-analytics-warning',
|
||
|
|
'text-analytics-info',
|
||
|
|
|
||
|
|
// Chart colors for dynamic generation
|
||
|
|
'text-chart-line1',
|
||
|
|
'text-chart-line2',
|
||
|
|
'text-chart-line3',
|
||
|
|
'text-chart-line4',
|
||
|
|
'text-chart-line5',
|
||
|
|
'bg-chart-line1',
|
||
|
|
'bg-chart-line2',
|
||
|
|
'bg-chart-line3',
|
||
|
|
'bg-chart-line4',
|
||
|
|
'bg-chart-line5',
|
||
|
|
],
|
||
|
|
|
||
|
|
// Content sources specific to analytics components
|
||
|
|
content: [
|
||
|
|
'src/components/features/analytics/**/*.rs',
|
||
|
|
'crates/client/src/components/analytics/**/*.rs',
|
||
|
|
'features/analytics/src/**/*.rs',
|
||
|
|
'templates/analytics/**/*.html',
|
||
|
|
],
|
||
|
|
|
||
|
|
// Preflights for analytics-specific base styles
|
||
|
|
preflights: [
|
||
|
|
{
|
||
|
|
getCSS: () => `
|
||
|
|
/* Analytics-specific global styles */
|
||
|
|
.analytics-dashboard {
|
||
|
|
--analytics-spacing: 1.5rem;
|
||
|
|
--analytics-border-radius: 0.5rem;
|
||
|
|
--analytics-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Chart container base styles */
|
||
|
|
.chart-container {
|
||
|
|
position: relative;
|
||
|
|
overflow: hidden;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Metric card hover effects */
|
||
|
|
.metric-card {
|
||
|
|
transition: all 0.2s ease-in-out;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Tooltip styling */
|
||
|
|
[data-tooltip]::after {
|
||
|
|
content: attr(data-tooltip);
|
||
|
|
position: absolute;
|
||
|
|
bottom: 100%;
|
||
|
|
left: 50%;
|
||
|
|
transform: translateX(-50%);
|
||
|
|
background: rgba(17, 24, 39, 0.9);
|
||
|
|
color: white;
|
||
|
|
padding: 0.25rem 0.5rem;
|
||
|
|
border-radius: 0.25rem;
|
||
|
|
font-size: 0.75rem;
|
||
|
|
white-space: nowrap;
|
||
|
|
opacity: 0;
|
||
|
|
pointer-events: none;
|
||
|
|
transition: opacity 0.2s;
|
||
|
|
z-index: 1000;
|
||
|
|
}
|
||
|
|
|
||
|
|
[data-tooltip]:hover::after {
|
||
|
|
opacity: 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Loading animation */
|
||
|
|
@keyframes pulse-analytics {
|
||
|
|
0%, 100% { opacity: 1; }
|
||
|
|
50% { opacity: 0.5; }
|
||
|
|
}
|
||
|
|
|
||
|
|
.loading-analytics {
|
||
|
|
animation: pulse-analytics 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
||
|
|
}
|
||
|
|
`
|
||
|
|
}
|
||
|
|
],
|
||
|
|
|
||
|
|
// Transformers for analytics-specific functionality
|
||
|
|
transformers: [
|
||
|
|
// Add data attributes for analytics tracking
|
||
|
|
{
|
||
|
|
name: 'analytics-tracking',
|
||
|
|
enforce: 'pre',
|
||
|
|
transform: (code: string) => {
|
||
|
|
// Add tracking attributes to analytics components
|
||
|
|
return code.replace(
|
||
|
|
/class="([^"]*metric-card[^"]*)"/g,
|
||
|
|
'class="$1" data-analytics-component="metric-card"'
|
||
|
|
)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
],
|
||
|
|
})
|