monacousa-portal/design-mockups/DESIGN-SYSTEM-V2.md

16 KiB

MonacoUSA Portal Design System V2

Professional Neumorphic & Glassmorphic Design Language


Table of Contents

  1. Design Philosophy
  2. Color System
  3. Typography
  4. Spacing & Layout
  5. Shadow System
  6. Component Library
  7. Morphing Dropdown Specification
  8. Animation Guidelines
  9. Responsive Design
  10. Implementation Examples

Design Philosophy

Core Principles

  • Professional & Inviting: Balancing corporate credibility with approachable design
  • Neumorphic Foundation: Soft UI with subtle depth and tactile feedback
  • Glassmorphic Accents: Strategic use of transparency and blur for interactive elements
  • Monaco Heritage: Incorporating national colors while maintaining modern aesthetics

Visual Hierarchy

  1. Primary Actions: Monaco Red gradient buttons with strong shadows
  2. Interactive Elements: Blue glassmorphic dropdowns and selects
  3. Content Cards: Neumorphic white/light gray surfaces
  4. Navigation: Subtle depth with hover transformations

Color System

Primary Palette - Monaco Red

$primary-50:  #FEF2F2;  // Lightest tint
$primary-100: #FEE2E2;
$primary-200: #FECACA;
$primary-300: #FCA5A5;
$primary-400: #F87171;
$primary-500: #EF4444;
$primary-600: #CC0000;  // Monaco Red (Main)
$primary-700: #990000;  // Monaco Dark Red
$primary-800: #660000;
$primary-900: #450A0A;  // Darkest shade

Secondary Palette - Interactive Blue

Used exclusively for dropdowns, selects, and interactive overlays:

$blue-50:  #EFF6FF;
$blue-100: #DBEAFE;
$blue-200: #BFDBFE;
$blue-300: #93C5FD;
$blue-400: #60A5FA;
$blue-500: #3B82F6;
$blue-600: #2563EB;
$blue-700: #1D4ED8;
$blue-800: #1E40AF;
$blue-900: #1E3A8A;

Neutral Palette

$neutral-50:  #F9FAFB;
$neutral-100: #F3F4F6;
$neutral-200: #E5E7EB;
$neutral-300: #D1D5DB;
$neutral-400: #9CA3AF;
$neutral-500: #6B7280;
$neutral-600: #4B5563;
$neutral-700: #374151;
$neutral-800: #1F2937;
$neutral-900: #111827;

Semantic Colors

$success: #10B981;  // Green
$warning: #F59E0B;  // Amber
$error:   #EF4444;  // Red
$info:    #3B82F6;  // Blue

Typography

Font Stack

font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Inter', Roboto, 
             'Helvetica Neue', Arial, sans-serif;

Type Scale

Name Size Line Height Usage
text-xs 0.75rem (12px) 1.5 Labels, captions
text-sm 0.875rem (14px) 1.5 Body small, form labels
text-base 1rem (16px) 1.5 Body default
text-lg 1.125rem (18px) 1.625 Body large
text-xl 1.25rem (20px) 1.625 H4
text-2xl 1.5rem (24px) 1.375 H3
text-3xl 1.875rem (30px) 1.375 H2
text-4xl 2.25rem (36px) 1.25 H1

Font Weights

  • font-normal: 400 - Body text
  • font-medium: 500 - Emphasis
  • font-semibold: 600 - Subheadings
  • font-bold: 700 - Headings

Spacing & Layout

Spacing Scale

$space-0:  0;
$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
$space-20: 5rem;      // 80px

Border Radius

$radius-sm:   0.375rem;  // 6px - Small elements
$radius-md:   0.5rem;    // 8px - Buttons
$radius-lg:   0.75rem;   // 12px - Cards, dropdowns
$radius-xl:   1rem;      // 16px - Large cards
$radius-2xl:  1.5rem;    // 24px - Hero sections
$radius-full: 9999px;    // Pills, avatars

Shadow System

Neumorphic Shadows

For cards and static elements:

// Soft elevation shadows
$shadow-soft-sm: 
  4px 4px 8px rgba(0, 0, 0, 0.08),
  -4px -4px 8px rgba(255, 255, 255, 0.95);

$shadow-soft-md: 
  8px 8px 16px rgba(0, 0, 0, 0.1),
  -8px -8px 16px rgba(255, 255, 255, 0.95);

$shadow-soft-lg: 
  12px 12px 24px rgba(0, 0, 0, 0.12),
  -12px -12px 24px rgba(255, 255, 255, 0.95);

// Inset shadows for pressed states
$shadow-inset-sm: 
  inset 4px 4px 8px rgba(0, 0, 0, 0.1),
  inset -4px -4px 8px rgba(255, 255, 255, 0.95);

Glassmorphic Shadows

For dropdowns and overlays:

$shadow-morphing: 
  0 10px 40px rgba(0, 0, 0, 0.12),
  0 2px 10px rgba(0, 0, 0, 0.08);

$shadow-glass: 
  0 8px 32px rgba(0, 0, 0, 0.1),
  0 0 0 1px rgba(255, 255, 255, 0.3);

Component Library

1. Buttons

Primary Button

.btn-primary {
  background: linear-gradient(135deg, $primary-600, $primary-700);
  color: white;
  padding: 0.75rem 1.5rem;
  border-radius: $radius-lg;
  box-shadow: 
    4px 4px 8px rgba(204, 0, 0, 0.3),
    -4px -4px 8px rgba(255, 255, 255, 0.95);
  
  &:hover {
    transform: translateY(-2px);
    box-shadow: 
      6px 6px 12px rgba(204, 0, 0, 0.4),
      -6px -6px 12px rgba(255, 255, 255, 0.95);
  }
  
  &:active {
    transform: translateY(0);
    box-shadow: $shadow-inset-sm;
  }
}

Neumorphic Button

.btn-neumorphic {
  background: linear-gradient(145deg, #ffffff, #f0f0f0);
  color: $neutral-700;
  padding: 0.75rem 1.5rem;
  border-radius: $radius-lg;
  box-shadow: $shadow-soft-sm;
  
  &:hover {
    box-shadow: $shadow-soft-md;
    transform: translateY(-1px);
  }
}

2. Cards

Neumorphic Card

.card-neumorphic {
  background: linear-gradient(145deg, #ffffff, #f0f0f0);
  border-radius: $radius-xl;
  padding: $space-6;
  box-shadow: $shadow-soft-md;
  
  &:hover {
    transform: translateY(-4px);
    box-shadow: $shadow-soft-lg;
  }
}

3. Form Inputs

Neumorphic Input

.input-neumorphic {
  background: $neutral-50;
  border: none;
  border-radius: $radius-lg;
  padding: $space-3 $space-4;
  box-shadow: $shadow-inset-sm;
  
  &:focus {
    outline: none;
    box-shadow: 
      $shadow-inset-md,
      0 0 0 3px rgba($primary-500, 0.1);
  }
}

Morphing Dropdown Specification

Overview

The morphing dropdown is a signature component that combines glassmorphism with smooth spring animations. It features a blue color scheme distinct from the primary Monaco red, creating clear visual hierarchy for interactive elements.

Visual Characteristics

Trigger State

.morphing-select-trigger {
  // Base styling
  height: 48px;
  padding: 0 1rem;
  border-radius: 12px;
  
  // Glassmorphic background
  background: rgba(239, 246, 255, 0.3);  // blue-50 with 30% opacity
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1px solid rgba(191, 219, 254, 0.3);  // blue-200 with 30% opacity
  
  // Typography
  color: #1E3A8A;  // blue-900
  font-size: 0.875rem;
  
  // Transition
  transition: all 0.3s ease;
  
  &:hover {
    background: rgba(219, 234, 254, 0.4);  // blue-100 with 40% opacity
    border-color: rgba(147, 197, 253, 0.4);  // blue-300 with 40% opacity
    transform: translateY(-1px);
    box-shadow: 0 4px 12px rgba(59, 130, 246, 0.1);
  }
  
  &.open {
    background: rgba(219, 234, 254, 0.5);
    border-color: rgba(96, 165, 250, 0.5);  // blue-400 with 50% opacity
    box-shadow: 
      0 0 0 3px rgba(59, 130, 246, 0.1),
      0 4px 12px rgba(59, 130, 246, 0.15);
  }
}

Dropdown Panel

.morphing-select-dropdown {
  // Glassmorphic container
  background: rgba(239, 246, 255, 0.95);  // blue-50 with 95% opacity
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border: 1px solid rgba(191, 219, 254, 0.3);
  border-radius: 12px;
  
  // Shadow
  box-shadow: 
    0 10px 40px rgba(0, 0, 0, 0.12),
    0 2px 10px rgba(0, 0, 0, 0.08);
  
  // Animation
  animation: morphIn 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  
  // Layout
  max-height: 300px;
  overflow: hidden;
}

Option Items

.morphing-select-option {
  padding: 0.625rem 0.75rem;
  border-radius: 8px;
  color: #1E3A8A;  // blue-900
  font-size: 0.875rem;
  transition: all 0.2s ease;
  
  &:hover {
    background: rgba(96, 165, 250, 0.2);  // blue-400 with 20% opacity
    transform: translateX(2px);
  }
  
  &.selected {
    background: rgba(59, 130, 246, 0.25);  // blue-500 with 25% opacity
    font-weight: 500;
  }
}

Option Groups

.morphing-select-optgroup-label {
  padding: 0.5rem 0.75rem 0.25rem;
  font-size: 0.75rem;
  font-weight: 600;
  color: #1D4ED8;  // blue-700
  text-transform: uppercase;
  letter-spacing: 0.05em;
  opacity: 0.8;
}

Animation Specifications

Spring Configuration

const TRANSITION = {
  type: 'spring',
  bounce: 0.05,    // Minimal bounce for professional feel
  duration: 0.3,   // Quick but smooth
};

Animation States

// Opening animation
@keyframes morphIn {
  from {
    opacity: 0;
    transform: scale(0.95) translateY(-10px);
  }
  to {
    opacity: 1;
    transform: scale(1) translateY(0);
  }
}

// Closing animation (reversed)
@keyframes morphOut {
  from {
    opacity: 1;
    transform: scale(1) translateY(0);
  }
  to {
    opacity: 0;
    transform: scale(0.95) translateY(-10px);
  }
}

Interaction Patterns

Click Outside

  • Clicking anywhere outside the dropdown closes it
  • Uses mousedown event for immediate response

Keyboard Navigation

  • Escape key closes the dropdown
  • Tab key navigates through options
  • Enter selects the focused option
  • Space toggles selection in multi-select

Touch Support

  • Touch events are handled identically to mouse events
  • Larger touch targets on mobile (min 44px)

Multi-Select Variant

Selected Tags

.morphing-select-tag {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.25rem 0.5rem;
  background: rgba(191, 219, 254, 0.6);  // blue-200 with 60% opacity
  border-radius: 6px;
  font-size: 0.75rem;
  
  // Remove button
  .tag-remove {
    color: #1D4ED8;  // blue-700
    cursor: pointer;
    
    &:hover {
      color: #1E3A8A;  // blue-900
    }
  }
}

Accessibility Features

  • ARIA attributes: aria-expanded, aria-controls, aria-modal
  • Role attributes: role="dialog" for dropdown panel
  • Keyboard navigation support
  • Focus management
  • Screen reader announcements

Implementation Guidelines

Vue/React Component Structure

interface SelectOption {
  value: string;
  label: string;
  disabled?: boolean;
}

interface OptionGroup {
  label: string;
  options: SelectOption[];
}

interface SelectProps {
  options?: SelectOption[];
  optgroups?: OptionGroup[];
  value?: string | string[];  // string[] for multi-select
  onValueChange?: (value: string | string[]) => void;
  placeholder?: string;
  disabled?: boolean;
  maxSelected?: number;  // For multi-select
  className?: string;
}

State Management

// Single Select
const [selectedValue, setSelectedValue] = useState('');
const [isOpen, setIsOpen] = useState(false);

// Multi-Select
const [selectedValues, setSelectedValues] = useState([]);
const [isOpen, setIsOpen] = useState(false);

Animation Guidelines

Timing Functions

$ease-smooth: cubic-bezier(0.4, 0, 0.2, 1);
$ease-bounce: cubic-bezier(0.68, -0.55, 0.265, 1.55);
$ease-out: cubic-bezier(0, 0, 0.2, 1);
$ease-in-out: cubic-bezier(0.4, 0, 0.6, 1);

Duration Scale

  • fast: 150ms - Micro interactions
  • base: 300ms - Standard transitions
  • slow: 500ms - Complex animations
  • slower: 700ms - Page transitions

Animation Principles

  1. Purpose: Every animation should have a clear purpose
  2. Performance: Use transform and opacity for GPU acceleration
  3. Consistency: Maintain consistent timing across similar interactions
  4. Subtlety: Animations should enhance, not distract

Responsive Design

Breakpoints

$breakpoint-sm: 640px;   // Mobile landscape
$breakpoint-md: 768px;   // Tablet portrait
$breakpoint-lg: 1024px;  // Tablet landscape
$breakpoint-xl: 1280px;  // Desktop
$breakpoint-2xl: 1536px; // Large desktop

Mobile Adaptations

Morphing Dropdown

  • Full-width on mobile
  • Bottom sheet presentation option
  • Larger touch targets (min 44px)
  • Reduced blur for performance

Navigation

  • Hamburger menu below tablet
  • Full-screen overlay navigation
  • Swipe gestures for sidebar

Cards

  • Single column layout on mobile
  • Reduced padding and margins
  • Simplified shadows for performance

Implementation Examples

Example 1: Login Form with Morphing Select

<div class="login-form">
  <!-- Email Input (Neumorphic) -->
  <div class="form-group">
    <label class="form-label">Email</label>
    <input type="email" class="input-neumorphic" placeholder="you@example.com">
  </div>
  
  <!-- Role Selector (Morphing Dropdown) -->
  <div class="form-group">
    <label class="form-label">Select Role</label>
    <div class="morphing-select">
      <div class="morphing-select-trigger">
        <span>Choose your role...</span>
        <svg class="chevron">...</svg>
      </div>
      <div class="morphing-select-dropdown">
        <div class="morphing-select-option">Member</div>
        <div class="morphing-select-option">Admin</div>
        <div class="morphing-select-option">Board Member</div>
      </div>
    </div>
  </div>
  
  <!-- Submit Button (Primary) -->
  <button class="btn-primary">Sign In</button>
</div>

Example 2: Dashboard Stats with Dropdown Filter

<div class="dashboard-header">
  <h1 class="page-title">Dashboard</h1>
  
  <!-- Time Period Filter (Morphing Dropdown) -->
  <div class="morphing-select">
    <div class="morphing-select-trigger">
      <span>Last 30 Days</span>
      <svg class="chevron">...</svg>
    </div>
    <div class="morphing-select-dropdown">
      <div class="morphing-select-optgroup">
        <div class="morphing-select-optgroup-label">Quick Ranges</div>
        <div class="morphing-select-option">Today</div>
        <div class="morphing-select-option">Last 7 Days</div>
        <div class="morphing-select-option selected">Last 30 Days</div>
      </div>
      <div class="morphing-select-optgroup">
        <div class="morphing-select-optgroup-label">Custom</div>
        <div class="morphing-select-option">Last Quarter</div>
        <div class="morphing-select-option">Last Year</div>
      </div>
    </div>
  </div>
</div>

<!-- Stats Cards (Neumorphic) -->
<div class="stats-grid">
  <div class="card-neumorphic stat-card">
    <div class="stat-value">2,847</div>
    <div class="stat-label">Total Members</div>
    <div class="stat-change positive">+12.5%</div>
  </div>
  <!-- More cards... -->
</div>

Design Tokens

For implementation in code, use these design tokens:

const designTokens = {
  colors: {
    primary: {
      50: '#FEF2F2',
      100: '#FEE2E2',
      200: '#FECACA',
      300: '#FCA5A5',
      400: '#F87171',
      500: '#EF4444',
      600: '#CC0000',  // Main brand color
      700: '#990000',
      800: '#660000',
      900: '#450A0A',
    },
    blue: {
      50: '#EFF6FF',
      100: '#DBEAFE',
      200: '#BFDBFE',
      300: '#93C5FD',
      400: '#60A5FA',
      500: '#3B82F6',
      600: '#2563EB',
      700: '#1D4ED8',
      800: '#1E40AF',
      900: '#1E3A8A',
    },
    // ... other colors
  },
  shadows: {
    'soft-sm': '4px 4px 8px rgba(0, 0, 0, 0.08), -4px -4px 8px rgba(255, 255, 255, 0.95)',
    'soft-md': '8px 8px 16px rgba(0, 0, 0, 0.1), -8px -8px 16px rgba(255, 255, 255, 0.95)',
    'soft-lg': '12px 12px 24px rgba(0, 0, 0, 0.12), -12px -12px 24px rgba(255, 255, 255, 0.95)',
    'morphing': '0 10px 40px rgba(0, 0, 0, 0.12), 0 2px 10px rgba(0, 0, 0, 0.08)',
  },
  animation: {
    duration: {
      fast: '150ms',
      base: '300ms',
      slow: '500ms',
    },
    ease: {
      smooth: 'cubic-bezier(0.4, 0, 0.2, 1)',
      bounce: 'cubic-bezier(0.68, -0.55, 0.265, 1.55)',
    },
  },
};

Version History

  • v2.0.0 - Initial release with Neumorphic & Glassmorphic design system
  • v2.0.1 - Added morphing dropdown specifications
  • v2.0.2 - Enhanced mobile responsive guidelines

Contact

For questions about implementing this design system, please contact the MonacoUSA Portal development team.