480 lines
12 KiB
Markdown
480 lines
12 KiB
Markdown
|
|
# MonacoUSA Portal Design System Implementation Guide
|
||
|
|
|
||
|
|
## 🎨 Overview
|
||
|
|
|
||
|
|
This comprehensive guide outlines the complete visual redesign of the MonacoUSA Portal, transitioning from a standard Vuetify implementation to a premium, custom design system featuring Monaco's signature red and white color scheme with modern glass morphism effects.
|
||
|
|
|
||
|
|
## 📋 Table of Contents
|
||
|
|
|
||
|
|
1. [Design Philosophy](#design-philosophy)
|
||
|
|
2. [Technical Stack](#technical-stack)
|
||
|
|
3. [Migration Strategy](#migration-strategy)
|
||
|
|
4. [Component Architecture](#component-architecture)
|
||
|
|
5. [Implementation Roadmap](#implementation-roadmap)
|
||
|
|
6. [Performance Guidelines](#performance-guidelines)
|
||
|
|
7. [Accessibility Standards](#accessibility-standards)
|
||
|
|
|
||
|
|
## Design Philosophy
|
||
|
|
|
||
|
|
### Core Principles
|
||
|
|
- **Premium Feel**: Every interaction should feel smooth and sophisticated
|
||
|
|
- **Brand Identity**: Monaco's red (#dc2626) as the primary accent color
|
||
|
|
- **Modern Aesthetics**: Glass morphism, subtle animations, and floating elements
|
||
|
|
- **User Experience**: Intuitive navigation with clear visual hierarchy
|
||
|
|
- **Performance**: Animations that enhance, not hinder, user experience
|
||
|
|
|
||
|
|
### Visual Language
|
||
|
|
- **Glass Morphism**: Semi-transparent surfaces with backdrop blur
|
||
|
|
- **Gradient Accents**: Dynamic gradients from Monaco red to deeper shades
|
||
|
|
- **Floating Elements**: Subtle shadows and depth for interactive components
|
||
|
|
- **Micro-animations**: Smooth transitions on hover, click, and state changes
|
||
|
|
- **Consistent Spacing**: 8px grid system for alignment and padding
|
||
|
|
|
||
|
|
## Technical Stack
|
||
|
|
|
||
|
|
### Current Setup
|
||
|
|
- **Framework**: Nuxt 3.8.2
|
||
|
|
- **UI Library**: Vuetify 3.4.7 (to be replaced)
|
||
|
|
- **Icons**: Material Design Icons (transitioning to Lucide)
|
||
|
|
- **Authentication**: Keycloak integration
|
||
|
|
- **Styling**: SCSS with scoped components
|
||
|
|
|
||
|
|
### New Additions
|
||
|
|
- **Animation Libraries**:
|
||
|
|
- VueUse Motion (preferred for Vue integration)
|
||
|
|
- GSAP (for complex animations)
|
||
|
|
- Anime.js (lightweight alternative)
|
||
|
|
- **Icons**: Lucide Icons (modern, customizable)
|
||
|
|
- **Utilities**: Tailwind CSS (for rapid prototyping)
|
||
|
|
- **State Management**: Pinia (already implemented)
|
||
|
|
|
||
|
|
## Migration Strategy
|
||
|
|
|
||
|
|
### Phase 1: Foundation (Week 1-2)
|
||
|
|
1. Set up new style architecture
|
||
|
|
2. Create base component library
|
||
|
|
3. Implement color system and typography
|
||
|
|
4. Set up animation utilities
|
||
|
|
|
||
|
|
### Phase 2: Core Components (Week 3-4)
|
||
|
|
1. Replace navigation components
|
||
|
|
2. Implement custom dropdowns and selects
|
||
|
|
3. Create button variants
|
||
|
|
4. Build card components
|
||
|
|
|
||
|
|
### Phase 3: Page Templates (Week 5-6)
|
||
|
|
1. Dashboard layouts
|
||
|
|
2. Data tables with glass effects
|
||
|
|
3. Form components
|
||
|
|
4. Modal and dialog systems
|
||
|
|
|
||
|
|
### Phase 4: Polish & Optimization (Week 7-8)
|
||
|
|
1. Performance tuning
|
||
|
|
2. Accessibility audit
|
||
|
|
3. Cross-browser testing
|
||
|
|
4. Documentation completion
|
||
|
|
|
||
|
|
## Component Architecture
|
||
|
|
|
||
|
|
### File Structure
|
||
|
|
```
|
||
|
|
components/
|
||
|
|
├── ui/ # Base UI components
|
||
|
|
│ ├── MonacoButton.vue
|
||
|
|
│ ├── GlassCard.vue
|
||
|
|
│ ├── AnimatedDropdown.vue
|
||
|
|
│ └── FloatingInput.vue
|
||
|
|
├── layout/ # Layout components
|
||
|
|
│ ├── DashboardSidebar.vue
|
||
|
|
│ ├── AppHeader.vue
|
||
|
|
│ └── PageContainer.vue
|
||
|
|
├── features/ # Feature-specific components
|
||
|
|
│ ├── MemberCard.vue
|
||
|
|
│ ├── EventCalendar.vue
|
||
|
|
│ └── DuesTracker.vue
|
||
|
|
└── shared/ # Shared utilities
|
||
|
|
├── LoadingSpinner.vue
|
||
|
|
├── ErrorBoundary.vue
|
||
|
|
└── TransitionWrapper.vue
|
||
|
|
```
|
||
|
|
|
||
|
|
### Component Guidelines
|
||
|
|
|
||
|
|
#### Naming Convention
|
||
|
|
- PascalCase for component files
|
||
|
|
- Prefix with "Monaco" for custom branded components
|
||
|
|
- Use descriptive names (e.g., `GlassDropdownMenu` not `Dropdown`)
|
||
|
|
|
||
|
|
#### Props & Events
|
||
|
|
```vue
|
||
|
|
<script setup lang="ts">
|
||
|
|
interface Props {
|
||
|
|
variant?: 'primary' | 'glass' | 'gradient'
|
||
|
|
size?: 'sm' | 'md' | 'lg'
|
||
|
|
animated?: boolean
|
||
|
|
}
|
||
|
|
|
||
|
|
const props = withDefaults(defineProps<Props>(), {
|
||
|
|
variant: 'primary',
|
||
|
|
size: 'md',
|
||
|
|
animated: true
|
||
|
|
})
|
||
|
|
|
||
|
|
const emit = defineEmits<{
|
||
|
|
click: [event: MouseEvent]
|
||
|
|
hover: [state: boolean]
|
||
|
|
}>()
|
||
|
|
</script>
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Composition API Pattern
|
||
|
|
```vue
|
||
|
|
<script setup lang="ts">
|
||
|
|
import { useMonacoTheme } from '~/composables/useMonacoTheme'
|
||
|
|
import { useGlassEffect } from '~/composables/useGlassEffect'
|
||
|
|
|
||
|
|
const { primaryColor, gradients } = useMonacoTheme()
|
||
|
|
const { glassStyle, blurAmount } = useGlassEffect()
|
||
|
|
</script>
|
||
|
|
```
|
||
|
|
|
||
|
|
## Implementation Roadmap
|
||
|
|
|
||
|
|
### Week 1: Setup & Foundation
|
||
|
|
- [ ] Configure animation libraries
|
||
|
|
- [ ] Set up SCSS architecture
|
||
|
|
- [ ] Create color system utilities
|
||
|
|
- [ ] Implement base glass morphism styles
|
||
|
|
- [ ] Set up Lucide icons integration
|
||
|
|
|
||
|
|
### Week 2: Core Components
|
||
|
|
- [ ] Custom dropdown components
|
||
|
|
- [ ] Button system with variants
|
||
|
|
- [ ] Card components with glass effects
|
||
|
|
- [ ] Form inputs with floating labels
|
||
|
|
- [ ] Navigation components
|
||
|
|
|
||
|
|
### Week 3: Dashboard Implementation
|
||
|
|
- [ ] Member dashboard layout
|
||
|
|
- [ ] Board dashboard enhancements
|
||
|
|
- [ ] Admin panel structure
|
||
|
|
- [ ] Widget components
|
||
|
|
- [ ] Chart integrations
|
||
|
|
|
||
|
|
### Week 4: Advanced Features
|
||
|
|
- [ ] Event calendar with animations
|
||
|
|
- [ ] Member management interface
|
||
|
|
- [ ] Dues payment flow
|
||
|
|
- [ ] Profile components
|
||
|
|
- [ ] Settings panels
|
||
|
|
|
||
|
|
### Week 5: Responsive Design
|
||
|
|
- [ ] Mobile navigation
|
||
|
|
- [ ] Tablet optimizations
|
||
|
|
- [ ] Touch interactions
|
||
|
|
- [ ] Gesture support
|
||
|
|
- [ ] PWA enhancements
|
||
|
|
|
||
|
|
### Week 6: Testing & Optimization
|
||
|
|
- [ ] Performance profiling
|
||
|
|
- [ ] Bundle optimization
|
||
|
|
- [ ] Lazy loading implementation
|
||
|
|
- [ ] Animation performance tuning
|
||
|
|
- [ ] Memory leak detection
|
||
|
|
|
||
|
|
## Performance Guidelines
|
||
|
|
|
||
|
|
### Animation Performance
|
||
|
|
```scss
|
||
|
|
// Use transform and opacity for animations
|
||
|
|
.animated-element {
|
||
|
|
will-change: transform, opacity;
|
||
|
|
transform: translateZ(0); // Enable hardware acceleration
|
||
|
|
}
|
||
|
|
|
||
|
|
// Avoid animating expensive properties
|
||
|
|
// BAD: width, height, padding, margin
|
||
|
|
// GOOD: transform, opacity, filter
|
||
|
|
```
|
||
|
|
|
||
|
|
### Component Optimization
|
||
|
|
```vue
|
||
|
|
<!-- Use v-show for frequently toggled elements -->
|
||
|
|
<div v-show="isVisible" class="glass-panel">
|
||
|
|
<!-- Content -->
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- Use v-if for conditionally rendered heavy components -->
|
||
|
|
<HeavyComponent v-if="shouldRender" />
|
||
|
|
|
||
|
|
<!-- Implement lazy loading for routes -->
|
||
|
|
<script setup>
|
||
|
|
const MemberDashboard = defineAsyncComponent(() =>
|
||
|
|
import('~/components/dashboards/MemberDashboard.vue')
|
||
|
|
)
|
||
|
|
</script>
|
||
|
|
```
|
||
|
|
|
||
|
|
### Bundle Size Management
|
||
|
|
- Tree-shake unused Vuetify components
|
||
|
|
- Lazy load animation libraries
|
||
|
|
- Use dynamic imports for heavy features
|
||
|
|
- Implement code splitting by route
|
||
|
|
- Optimize images with next-gen formats
|
||
|
|
|
||
|
|
## Accessibility Standards
|
||
|
|
|
||
|
|
### WCAG 2.1 Compliance
|
||
|
|
- **Color Contrast**: Ensure 4.5:1 ratio for normal text
|
||
|
|
- **Focus Indicators**: Clear visual focus states
|
||
|
|
- **Keyboard Navigation**: Full keyboard support
|
||
|
|
- **Screen Readers**: Proper ARIA labels
|
||
|
|
- **Motion Sensitivity**: Respect prefers-reduced-motion
|
||
|
|
|
||
|
|
### Implementation Examples
|
||
|
|
```vue
|
||
|
|
<template>
|
||
|
|
<button
|
||
|
|
:aria-label="ariaLabel"
|
||
|
|
:aria-pressed="isPressed"
|
||
|
|
@click="handleClick"
|
||
|
|
@keydown.enter="handleClick"
|
||
|
|
@keydown.space.prevent="handleClick"
|
||
|
|
class="monaco-button"
|
||
|
|
:class="{ 'reduced-motion': prefersReducedMotion }"
|
||
|
|
>
|
||
|
|
<slot />
|
||
|
|
</button>
|
||
|
|
</template>
|
||
|
|
|
||
|
|
<script setup>
|
||
|
|
const prefersReducedMotion = useMediaQuery('(prefers-reduced-motion: reduce)')
|
||
|
|
</script>
|
||
|
|
|
||
|
|
<style scoped>
|
||
|
|
.monaco-button {
|
||
|
|
transition: all 0.3s ease;
|
||
|
|
}
|
||
|
|
|
||
|
|
.monaco-button.reduced-motion {
|
||
|
|
transition: none;
|
||
|
|
}
|
||
|
|
</style>
|
||
|
|
```
|
||
|
|
|
||
|
|
## Style Guidelines
|
||
|
|
|
||
|
|
### Color System
|
||
|
|
```scss
|
||
|
|
// Primary Colors
|
||
|
|
$monaco-red: #dc2626;
|
||
|
|
$monaco-red-dark: #b91c1c;
|
||
|
|
$monaco-red-light: #ef4444;
|
||
|
|
$monaco-white: #ffffff;
|
||
|
|
|
||
|
|
// Gradients
|
||
|
|
$monaco-gradient: linear-gradient(135deg, $monaco-red 0%, $monaco-red-dark 100%);
|
||
|
|
$monaco-gradient-reverse: linear-gradient(135deg, $monaco-red-light 0%, $monaco-red 100%);
|
||
|
|
|
||
|
|
// Glass Effects
|
||
|
|
$glass-bg: rgba(255, 255, 255, 0.7);
|
||
|
|
$glass-border: rgba(255, 255, 255, 0.3);
|
||
|
|
$glass-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
|
||
|
|
$glass-blur: 20px;
|
||
|
|
```
|
||
|
|
|
||
|
|
### Typography Scale
|
||
|
|
```scss
|
||
|
|
// Font Family
|
||
|
|
$font-primary: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
|
||
|
|
$font-mono: 'Fira Code', 'Monaco', monospace;
|
||
|
|
|
||
|
|
// Font Sizes
|
||
|
|
$text-xs: 0.75rem; // 12px
|
||
|
|
$text-sm: 0.875rem; // 14px
|
||
|
|
$text-base: 1rem; // 16px
|
||
|
|
$text-lg: 1.125rem; // 18px
|
||
|
|
$text-xl: 1.25rem; // 20px
|
||
|
|
$text-2xl: 1.5rem; // 24px
|
||
|
|
$text-3xl: 1.875rem; // 30px
|
||
|
|
$text-4xl: 2.25rem; // 36px
|
||
|
|
```
|
||
|
|
|
||
|
|
### Spacing System
|
||
|
|
```scss
|
||
|
|
// Based on 8px grid
|
||
|
|
$space-1: 0.25rem; // 4px
|
||
|
|
$space-2: 0.5rem; // 8px
|
||
|
|
$space-3: 0.75rem; // 12px
|
||
|
|
$space-4: 1rem; // 16px
|
||
|
|
$space-5: 1.25rem; // 20px
|
||
|
|
$space-6: 1.5rem; // 24px
|
||
|
|
$space-8: 2rem; // 32px
|
||
|
|
$space-10: 2.5rem; // 40px
|
||
|
|
$space-12: 3rem; // 48px
|
||
|
|
$space-16: 4rem; // 64px
|
||
|
|
```
|
||
|
|
|
||
|
|
## Component Examples
|
||
|
|
|
||
|
|
### Glass Card Component
|
||
|
|
```vue
|
||
|
|
<template>
|
||
|
|
<div class="glass-card" :class="[sizeClass, variantClass]">
|
||
|
|
<div v-if="hasHeader" class="glass-card-header">
|
||
|
|
<slot name="header" />
|
||
|
|
</div>
|
||
|
|
<div class="glass-card-body">
|
||
|
|
<slot />
|
||
|
|
</div>
|
||
|
|
<div v-if="hasFooter" class="glass-card-footer">
|
||
|
|
<slot name="footer" />
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</template>
|
||
|
|
|
||
|
|
<script setup lang="ts">
|
||
|
|
interface Props {
|
||
|
|
size?: 'sm' | 'md' | 'lg'
|
||
|
|
variant?: 'light' | 'dark' | 'colored'
|
||
|
|
}
|
||
|
|
|
||
|
|
const props = withDefaults(defineProps<Props>(), {
|
||
|
|
size: 'md',
|
||
|
|
variant: 'light'
|
||
|
|
})
|
||
|
|
|
||
|
|
const slots = useSlots()
|
||
|
|
const hasHeader = computed(() => !!slots.header)
|
||
|
|
const hasFooter = computed(() => !!slots.footer)
|
||
|
|
|
||
|
|
const sizeClass = computed(() => `glass-card--${props.size}`)
|
||
|
|
const variantClass = computed(() => `glass-card--${props.variant}`)
|
||
|
|
</script>
|
||
|
|
|
||
|
|
<style scoped lang="scss">
|
||
|
|
.glass-card {
|
||
|
|
background: rgba(255, 255, 255, 0.7);
|
||
|
|
backdrop-filter: blur(20px);
|
||
|
|
border-radius: 16px;
|
||
|
|
border: 1px solid rgba(255, 255, 255, 0.3);
|
||
|
|
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
|
||
|
|
overflow: hidden;
|
||
|
|
transition: all 0.3s ease;
|
||
|
|
|
||
|
|
&:hover {
|
||
|
|
transform: translateY(-2px);
|
||
|
|
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.15);
|
||
|
|
}
|
||
|
|
|
||
|
|
&--dark {
|
||
|
|
background: rgba(0, 0, 0, 0.7);
|
||
|
|
border-color: rgba(255, 255, 255, 0.1);
|
||
|
|
}
|
||
|
|
|
||
|
|
&--colored {
|
||
|
|
background: linear-gradient(135deg,
|
||
|
|
rgba(220, 38, 38, 0.1) 0%,
|
||
|
|
rgba(185, 28, 28, 0.1) 100%);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
</style>
|
||
|
|
```
|
||
|
|
|
||
|
|
## Testing Strategy
|
||
|
|
|
||
|
|
### Unit Testing
|
||
|
|
```typescript
|
||
|
|
// components/__tests__/MonacoButton.spec.ts
|
||
|
|
import { mount } from '@vue/test-utils'
|
||
|
|
import MonacoButton from '~/components/ui/MonacoButton.vue'
|
||
|
|
|
||
|
|
describe('MonacoButton', () => {
|
||
|
|
it('renders with correct variant class', () => {
|
||
|
|
const wrapper = mount(MonacoButton, {
|
||
|
|
props: { variant: 'gradient' }
|
||
|
|
})
|
||
|
|
expect(wrapper.classes()).toContain('monaco-button--gradient')
|
||
|
|
})
|
||
|
|
|
||
|
|
it('emits click event', async () => {
|
||
|
|
const wrapper = mount(MonacoButton)
|
||
|
|
await wrapper.trigger('click')
|
||
|
|
expect(wrapper.emitted('click')).toHaveLength(1)
|
||
|
|
})
|
||
|
|
})
|
||
|
|
```
|
||
|
|
|
||
|
|
### E2E Testing
|
||
|
|
```typescript
|
||
|
|
// e2e/dashboard.spec.ts
|
||
|
|
import { test, expect } from '@playwright/test'
|
||
|
|
|
||
|
|
test('dashboard loads with glass morphism effects', async ({ page }) => {
|
||
|
|
await page.goto('/dashboard')
|
||
|
|
|
||
|
|
const glassCard = page.locator('.glass-card').first()
|
||
|
|
await expect(glassCard).toBeVisible()
|
||
|
|
|
||
|
|
const styles = await glassCard.evaluate(el =>
|
||
|
|
window.getComputedStyle(el)
|
||
|
|
)
|
||
|
|
expect(styles.backdropFilter).toContain('blur')
|
||
|
|
})
|
||
|
|
```
|
||
|
|
|
||
|
|
## Deployment Checklist
|
||
|
|
|
||
|
|
### Pre-deployment
|
||
|
|
- [ ] Run full test suite
|
||
|
|
- [ ] Check bundle size (<500KB initial)
|
||
|
|
- [ ] Validate accessibility scores
|
||
|
|
- [ ] Test on all target browsers
|
||
|
|
- [ ] Optimize images and assets
|
||
|
|
- [ ] Review security headers
|
||
|
|
|
||
|
|
### Performance Metrics
|
||
|
|
- First Contentful Paint: <1.5s
|
||
|
|
- Time to Interactive: <3s
|
||
|
|
- Cumulative Layout Shift: <0.1
|
||
|
|
- First Input Delay: <100ms
|
||
|
|
- Lighthouse Score: >90
|
||
|
|
|
||
|
|
### Browser Support
|
||
|
|
- Chrome 90+
|
||
|
|
- Firefox 88+
|
||
|
|
- Safari 14+
|
||
|
|
- Edge 90+
|
||
|
|
- Mobile Safari 14+
|
||
|
|
- Chrome Mobile 90+
|
||
|
|
|
||
|
|
## Resources
|
||
|
|
|
||
|
|
### Documentation
|
||
|
|
- [Vue 3 Composition API](https://vuejs.org/guide/extras/composition-api-faq.html)
|
||
|
|
- [Nuxt 3 Documentation](https://nuxt.com/docs)
|
||
|
|
- [VueUse Motion](https://motion.vueuse.org/)
|
||
|
|
- [GSAP Documentation](https://greensock.com/docs/)
|
||
|
|
- [Lucide Icons](https://lucide.dev/)
|
||
|
|
|
||
|
|
### Design Inspiration
|
||
|
|
- [Glass Morphism Examples](https://glassmorphism.com/)
|
||
|
|
- [Monaco Brand Guidelines](internal-link)
|
||
|
|
- [Material Design 3](https://m3.material.io/)
|
||
|
|
|
||
|
|
### Tools
|
||
|
|
- [Contrast Checker](https://webaim.org/resources/contrastchecker/)
|
||
|
|
- [Bundle Analyzer](https://github.com/nuxt/devtools)
|
||
|
|
- [Lighthouse CI](https://github.com/GoogleChrome/lighthouse-ci)
|
||
|
|
|
||
|
|
## Support
|
||
|
|
|
||
|
|
For questions or assistance with implementation:
|
||
|
|
- Technical Lead: [Contact Info]
|
||
|
|
- Design Team: [Contact Info]
|
||
|
|
- Documentation: This guide and `/Design` folder
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
*Last Updated: December 2024*
|
||
|
|
*Version: 1.0.0*
|