design mockups
Build And Push Image / docker (push) Successful in 2m3s
Details
Build And Push Image / docker (push) Successful in 2m3s
Details
This commit is contained in:
parent
4d24315103
commit
e949df311b
|
|
@ -42,7 +42,9 @@
|
||||||
"mcp__serena__insert_after_symbol",
|
"mcp__serena__insert_after_symbol",
|
||||||
"mcp__serena__replace_symbol_body",
|
"mcp__serena__replace_symbol_body",
|
||||||
"mcp__playwright__browser_fill_form",
|
"mcp__playwright__browser_fill_form",
|
||||||
"mcp__zen__debug"
|
"mcp__zen__debug",
|
||||||
|
"Bash(Copy-Item -Path \"Z:\\Repos\\monacousa-portal\\design-mockups\\pages\\auth\\ProfessionalLogin.vue\" -Destination \"Z:\\Repos\\monacousa-portal\\pages\\mockups\\login.vue\")",
|
||||||
|
"Bash(Remove-Item -Path \"Z:\\Repos\\monacousa-portal\\pages\\mockups\" -Recurse -Force)"
|
||||||
],
|
],
|
||||||
"deny": [],
|
"deny": [],
|
||||||
"ask": []
|
"ask": []
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,690 @@
|
||||||
|
# MonacoUSA Portal Design System V2
|
||||||
|
## Professional Neumorphic & Glassmorphic Design Language
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Table of Contents
|
||||||
|
1. [Design Philosophy](#design-philosophy)
|
||||||
|
2. [Color System](#color-system)
|
||||||
|
3. [Typography](#typography)
|
||||||
|
4. [Spacing & Layout](#spacing--layout)
|
||||||
|
5. [Shadow System](#shadow-system)
|
||||||
|
6. [Component Library](#component-library)
|
||||||
|
7. [Morphing Dropdown Specification](#morphing-dropdown-specification)
|
||||||
|
8. [Animation Guidelines](#animation-guidelines)
|
||||||
|
9. [Responsive Design](#responsive-design)
|
||||||
|
10. [Implementation Examples](#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
|
||||||
|
```scss
|
||||||
|
$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:
|
||||||
|
```scss
|
||||||
|
$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
|
||||||
|
```scss
|
||||||
|
$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
|
||||||
|
```scss
|
||||||
|
$success: #10B981; // Green
|
||||||
|
$warning: #F59E0B; // Amber
|
||||||
|
$error: #EF4444; // Red
|
||||||
|
$info: #3B82F6; // Blue
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Typography
|
||||||
|
|
||||||
|
### Font Stack
|
||||||
|
```css
|
||||||
|
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
|
||||||
|
```scss
|
||||||
|
$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
|
||||||
|
```scss
|
||||||
|
$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:
|
||||||
|
```scss
|
||||||
|
// 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:
|
||||||
|
```scss
|
||||||
|
$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
|
||||||
|
```scss
|
||||||
|
.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
|
||||||
|
```scss
|
||||||
|
.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
|
||||||
|
```scss
|
||||||
|
.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
|
||||||
|
```scss
|
||||||
|
.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
|
||||||
|
```scss
|
||||||
|
.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
|
||||||
|
```scss
|
||||||
|
.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
|
||||||
|
```scss
|
||||||
|
.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
|
||||||
|
```scss
|
||||||
|
.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
|
||||||
|
```javascript
|
||||||
|
const TRANSITION = {
|
||||||
|
type: 'spring',
|
||||||
|
bounce: 0.05, // Minimal bounce for professional feel
|
||||||
|
duration: 0.3, // Quick but smooth
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Animation States
|
||||||
|
```javascript
|
||||||
|
// 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
|
||||||
|
```scss
|
||||||
|
.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
|
||||||
|
```typescript
|
||||||
|
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
|
||||||
|
```javascript
|
||||||
|
// 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
|
||||||
|
```scss
|
||||||
|
$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
|
||||||
|
```scss
|
||||||
|
$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
|
||||||
|
```html
|
||||||
|
<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
|
||||||
|
```html
|
||||||
|
<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:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
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.
|
||||||
|
|
@ -80,7 +80,11 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
// No additional logic needed for this index page
|
// Disable authentication for mockups
|
||||||
|
definePageMeta({
|
||||||
|
auth: false,
|
||||||
|
layout: false
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
|
||||||
|
|
@ -193,9 +193,15 @@
|
||||||
import { ref, onMounted } from 'vue';
|
import { ref, onMounted } from 'vue';
|
||||||
import NeumorphicCard from '../../components/core/NeumorphicCard.vue';
|
import NeumorphicCard from '../../components/core/NeumorphicCard.vue';
|
||||||
import ProfessionalButton from '../../components/core/ProfessionalButton.vue';
|
import ProfessionalButton from '../../components/core/ProfessionalButton.vue';
|
||||||
import StatCard from '../../components/data/StatCard.vue';
|
import StatCard from '../../components/core/StatCard.vue';
|
||||||
import Chart from 'chart.js/auto';
|
import Chart from 'chart.js/auto';
|
||||||
|
|
||||||
|
// Disable authentication for mockup
|
||||||
|
definePageMeta({
|
||||||
|
auth: false,
|
||||||
|
layout: false
|
||||||
|
});
|
||||||
|
|
||||||
// Icons (simplified for demo)
|
// Icons (simplified for demo)
|
||||||
const HomeIcon = { template: '<svg fill="currentColor" viewBox="0 0 20 20"><path d="M10.707 2.293a1 1 0 00-1.414 0l-7 7a1 1 0 001.414 1.414L4 10.414V17a1 1 0 001 1h2a1 1 0 001-1v-2a1 1 0 011-1h2a1 1 0 011 1v2a1 1 0 001 1h2a1 1 0 001-1v-6.586l.293.293a1 1 0 001.414-1.414l-7-7z"/></svg>' };
|
const HomeIcon = { template: '<svg fill="currentColor" viewBox="0 0 20 20"><path d="M10.707 2.293a1 1 0 00-1.414 0l-7 7a1 1 0 001.414 1.414L4 10.414V17a1 1 0 001 1h2a1 1 0 001-1v-2a1 1 0 011-1h2a1 1 0 011 1v2a1 1 0 001 1h2a1 1 0 001-1v-6.586l.293.293a1 1 0 001.414-1.414l-7-7z"/></svg>' };
|
||||||
const UsersIcon = { template: '<svg fill="currentColor" viewBox="0 0 20 20"><path d="M9 6a3 3 0 11-6 0 3 3 0 016 0zM17 6a3 3 0 11-6 0 3 3 0 016 0zM12.93 17c.046-.327.07-.66.07-1a6.97 6.97 0 00-1.5-4.33A5 5 0 0119 16v1h-6.07zM6 11a5 5 0 015 5v1H1v-1a5 5 0 015-5z"/></svg>' };
|
const UsersIcon = { template: '<svg fill="currentColor" viewBox="0 0 20 20"><path d="M9 6a3 3 0 11-6 0 3 3 0 016 0zM17 6a3 3 0 11-6 0 3 3 0 016 0zM12.93 17c.046-.327.07-.66.07-1a6.97 6.97 0 00-1.5-4.33A5 5 0 0119 16v1h-6.07zM6 11a5 5 0 015 5v1H1v-1a5 5 0 015-5z"/></svg>' };
|
||||||
|
|
|
||||||
|
|
@ -121,6 +121,12 @@ import { ref } from 'vue';
|
||||||
import NeumorphicCard from '../../components/core/NeumorphicCard.vue';
|
import NeumorphicCard from '../../components/core/NeumorphicCard.vue';
|
||||||
import ProfessionalButton from '../../components/core/ProfessionalButton.vue';
|
import ProfessionalButton from '../../components/core/ProfessionalButton.vue';
|
||||||
|
|
||||||
|
// Disable authentication for mockup
|
||||||
|
definePageMeta({
|
||||||
|
auth: false,
|
||||||
|
layout: false
|
||||||
|
});
|
||||||
|
|
||||||
// Data
|
// Data
|
||||||
const credentials = ref({
|
const credentials = ref({
|
||||||
email: '',
|
email: '',
|
||||||
|
|
|
||||||
|
|
@ -284,6 +284,12 @@ import NeumorphicCard from '../../components/core/NeumorphicCard.vue';
|
||||||
import ProfessionalButton from '../../components/core/ProfessionalButton.vue';
|
import ProfessionalButton from '../../components/core/ProfessionalButton.vue';
|
||||||
import StatCard from '../../components/core/StatCard.vue';
|
import StatCard from '../../components/core/StatCard.vue';
|
||||||
|
|
||||||
|
// Disable authentication for mockup
|
||||||
|
definePageMeta({
|
||||||
|
auth: false,
|
||||||
|
layout: false
|
||||||
|
});
|
||||||
|
|
||||||
// Data
|
// Data
|
||||||
const sidebarCollapsed = ref(false);
|
const sidebarCollapsed = ref(false);
|
||||||
const currentDate = ref(new Date().toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' }));
|
const currentDate = ref(new Date().toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' }));
|
||||||
|
|
|
||||||
|
|
@ -330,6 +330,12 @@ import NeumorphicCard from '../../components/core/NeumorphicCard.vue';
|
||||||
import ProfessionalButton from '../../components/core/ProfessionalButton.vue';
|
import ProfessionalButton from '../../components/core/ProfessionalButton.vue';
|
||||||
import StatCard from '../../components/core/StatCard.vue';
|
import StatCard from '../../components/core/StatCard.vue';
|
||||||
|
|
||||||
|
// Disable authentication for mockup
|
||||||
|
definePageMeta({
|
||||||
|
auth: false,
|
||||||
|
layout: false
|
||||||
|
});
|
||||||
|
|
||||||
// Data
|
// Data
|
||||||
const mobileMenuOpen = ref(false);
|
const mobileMenuOpen = ref(false);
|
||||||
const profileMenuOpen = ref(false);
|
const profileMenuOpen = ref(false);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,361 @@
|
||||||
|
// MonacoUSA Portal Design System
|
||||||
|
// Professional Neumorphic Design with Enhanced Components
|
||||||
|
|
||||||
|
// ========================================
|
||||||
|
// 1. COLOR PALETTE
|
||||||
|
// ========================================
|
||||||
|
|
||||||
|
// Brand Colors
|
||||||
|
$monaco-red: #CC0000;
|
||||||
|
$monaco-dark-red: #990000;
|
||||||
|
$monaco-light-red: #FF3333;
|
||||||
|
|
||||||
|
// Primary Colors (Monaco Red)
|
||||||
|
$primary-50: #FEF2F2;
|
||||||
|
$primary-100: #FEE2E2;
|
||||||
|
$primary-200: #FECACA;
|
||||||
|
$primary-300: #FCA5A5;
|
||||||
|
$primary-400: #F87171;
|
||||||
|
$primary-500: #EF4444;
|
||||||
|
$primary-600: $monaco-red;
|
||||||
|
$primary-700: $monaco-dark-red;
|
||||||
|
$primary-800: #660000;
|
||||||
|
$primary-900: #450A0A;
|
||||||
|
|
||||||
|
// Neutral Colors
|
||||||
|
$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;
|
||||||
|
|
||||||
|
// Blue Colors (for dropdowns and accents)
|
||||||
|
$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;
|
||||||
|
|
||||||
|
// Semantic Colors
|
||||||
|
$success-500: #10B981;
|
||||||
|
$warning-500: #F59E0B;
|
||||||
|
$error-500: #EF4444;
|
||||||
|
$info-500: #3B82F6;
|
||||||
|
|
||||||
|
// ========================================
|
||||||
|
// 2. TYPOGRAPHY
|
||||||
|
// ========================================
|
||||||
|
|
||||||
|
$font-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
||||||
|
$font-heading: 'Inter', $font-sans;
|
||||||
|
$font-mono: 'Fira Code', 'Courier New', 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
|
||||||
|
$text-5xl: 3rem; // 48px
|
||||||
|
|
||||||
|
// Font Weights
|
||||||
|
$font-light: 300;
|
||||||
|
$font-normal: 400;
|
||||||
|
$font-medium: 500;
|
||||||
|
$font-semibold: 600;
|
||||||
|
$font-bold: 700;
|
||||||
|
|
||||||
|
// Line Heights
|
||||||
|
$leading-tight: 1.25;
|
||||||
|
$leading-normal: 1.5;
|
||||||
|
$leading-relaxed: 1.625;
|
||||||
|
|
||||||
|
// ========================================
|
||||||
|
// 3. SPACING SYSTEM
|
||||||
|
// ========================================
|
||||||
|
|
||||||
|
$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
|
||||||
|
|
||||||
|
// ========================================
|
||||||
|
// 4. NEUMORPHIC SHADOWS
|
||||||
|
// ========================================
|
||||||
|
|
||||||
|
// Soft Shadows (light theme)
|
||||||
|
$shadow-soft-xs:
|
||||||
|
2px 2px 4px rgba(0, 0, 0, 0.07),
|
||||||
|
-2px -2px 4px rgba(255, 255, 255, 0.95);
|
||||||
|
|
||||||
|
$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);
|
||||||
|
|
||||||
|
$shadow-soft-xl:
|
||||||
|
16px 16px 32px rgba(0, 0, 0, 0.14),
|
||||||
|
-16px -16px 32px rgba(255, 255, 255, 0.95);
|
||||||
|
|
||||||
|
// Inset Shadows (for pressed/input states)
|
||||||
|
$shadow-inset-sm:
|
||||||
|
inset 4px 4px 8px rgba(0, 0, 0, 0.1),
|
||||||
|
inset -4px -4px 8px rgba(255, 255, 255, 0.95);
|
||||||
|
|
||||||
|
$shadow-inset-md:
|
||||||
|
inset 6px 6px 12px rgba(0, 0, 0, 0.15),
|
||||||
|
inset -6px -6px 12px rgba(255, 255, 255, 0.95);
|
||||||
|
|
||||||
|
// Glassmorphic Shadow
|
||||||
|
$shadow-glass:
|
||||||
|
0 8px 32px rgba(0, 0, 0, 0.1),
|
||||||
|
0 0 0 1px rgba(255, 255, 255, 0.3);
|
||||||
|
|
||||||
|
// Morphing Dropdown Shadow
|
||||||
|
$shadow-morphing:
|
||||||
|
0 10px 40px rgba(0, 0, 0, 0.12),
|
||||||
|
0 2px 10px rgba(0, 0, 0, 0.08);
|
||||||
|
|
||||||
|
// ========================================
|
||||||
|
// 5. BORDER RADIUS
|
||||||
|
// ========================================
|
||||||
|
|
||||||
|
$radius-sm: 0.375rem; // 6px
|
||||||
|
$radius-md: 0.5rem; // 8px
|
||||||
|
$radius-lg: 0.75rem; // 12px
|
||||||
|
$radius-xl: 1rem; // 16px
|
||||||
|
$radius-2xl: 1.5rem; // 24px
|
||||||
|
$radius-3xl: 2rem; // 32px
|
||||||
|
$radius-full: 9999px;
|
||||||
|
|
||||||
|
// ========================================
|
||||||
|
// 6. TRANSITIONS
|
||||||
|
// ========================================
|
||||||
|
|
||||||
|
$transition-base: 0.3s ease;
|
||||||
|
$transition-fast: 0.15s ease;
|
||||||
|
$transition-slow: 0.5s ease;
|
||||||
|
|
||||||
|
// Spring Animation (for dropdowns)
|
||||||
|
$spring-bounce: cubic-bezier(0.68, -0.55, 0.265, 1.55);
|
||||||
|
$spring-smooth: cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
|
||||||
|
// ========================================
|
||||||
|
// 7. BREAKPOINTS
|
||||||
|
// ========================================
|
||||||
|
|
||||||
|
$breakpoint-sm: 640px;
|
||||||
|
$breakpoint-md: 768px;
|
||||||
|
$breakpoint-lg: 1024px;
|
||||||
|
$breakpoint-xl: 1280px;
|
||||||
|
$breakpoint-2xl: 1536px;
|
||||||
|
|
||||||
|
// ========================================
|
||||||
|
// 8. Z-INDEX LAYERS
|
||||||
|
// ========================================
|
||||||
|
|
||||||
|
$z-base: 0;
|
||||||
|
$z-dropdown: 10;
|
||||||
|
$z-sticky: 20;
|
||||||
|
$z-overlay: 30;
|
||||||
|
$z-modal: 40;
|
||||||
|
$z-popover: 50;
|
||||||
|
$z-tooltip: 60;
|
||||||
|
$z-notification: 70;
|
||||||
|
|
||||||
|
// ========================================
|
||||||
|
// 9. GLASSMORPHISM MIXINS
|
||||||
|
// ========================================
|
||||||
|
|
||||||
|
@mixin glassmorphism($bg-opacity: 0.8, $blur: 12px) {
|
||||||
|
background: rgba(255, 255, 255, $bg-opacity);
|
||||||
|
backdrop-filter: blur($blur);
|
||||||
|
-webkit-backdrop-filter: blur($blur);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin glassmorphism-blue($bg-opacity: 0.3, $blur: 12px) {
|
||||||
|
background: rgba($blue-50, $bg-opacity);
|
||||||
|
backdrop-filter: blur($blur);
|
||||||
|
-webkit-backdrop-filter: blur($blur);
|
||||||
|
border: 1px solid rgba($blue-200, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========================================
|
||||||
|
// 10. COMPONENT MIXINS
|
||||||
|
// ========================================
|
||||||
|
|
||||||
|
// Neumorphic Card
|
||||||
|
@mixin neumorphic-card($elevation: 'md') {
|
||||||
|
background: linear-gradient(145deg, #ffffff, #f0f0f0);
|
||||||
|
border-radius: $radius-xl;
|
||||||
|
|
||||||
|
@if $elevation == 'sm' {
|
||||||
|
box-shadow: $shadow-soft-sm;
|
||||||
|
} @else if $elevation == 'md' {
|
||||||
|
box-shadow: $shadow-soft-md;
|
||||||
|
} @else if $elevation == 'lg' {
|
||||||
|
box-shadow: $shadow-soft-lg;
|
||||||
|
} @else if $elevation == 'xl' {
|
||||||
|
box-shadow: $shadow-soft-xl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Neumorphic Button
|
||||||
|
@mixin neumorphic-button() {
|
||||||
|
background: linear-gradient(145deg, #ffffff, #f0f0f0);
|
||||||
|
box-shadow: $shadow-soft-sm;
|
||||||
|
transition: all $transition-base;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
box-shadow: $shadow-soft-md;
|
||||||
|
transform: translateY(-2px);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
box-shadow: $shadow-inset-sm;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Morphing Dropdown
|
||||||
|
@mixin morphing-dropdown() {
|
||||||
|
@include glassmorphism-blue(0.8, 16px);
|
||||||
|
box-shadow: $shadow-morphing;
|
||||||
|
border-radius: $radius-lg;
|
||||||
|
overflow: hidden;
|
||||||
|
animation: morphIn 0.3s $spring-smooth;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Focus Ring
|
||||||
|
@mixin focus-ring($color: $primary-500) {
|
||||||
|
&:focus {
|
||||||
|
outline: none;
|
||||||
|
box-shadow:
|
||||||
|
0 0 0 3px rgba($color, 0.1),
|
||||||
|
$shadow-soft-md;
|
||||||
|
border-color: rgba($color, 0.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========================================
|
||||||
|
// 11. ANIMATIONS
|
||||||
|
// ========================================
|
||||||
|
|
||||||
|
@keyframes morphIn {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: scale(0.95) translateY(-10px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: scale(1) translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes slideDown {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-10px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadeIn {
|
||||||
|
from { opacity: 0; }
|
||||||
|
to { opacity: 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes pulse {
|
||||||
|
0%, 100% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========================================
|
||||||
|
// 12. UTILITY CLASSES
|
||||||
|
// ========================================
|
||||||
|
|
||||||
|
.backdrop-blur {
|
||||||
|
backdrop-filter: blur(12px);
|
||||||
|
-webkit-backdrop-filter: blur(12px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.glass-effect {
|
||||||
|
@include glassmorphism();
|
||||||
|
}
|
||||||
|
|
||||||
|
.glass-blue {
|
||||||
|
@include glassmorphism-blue();
|
||||||
|
}
|
||||||
|
|
||||||
|
.shadow-neumorphic {
|
||||||
|
box-shadow: $shadow-soft-md;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-gradient {
|
||||||
|
background: linear-gradient(135deg, $primary-600, $primary-800);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
background-clip: text;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========================================
|
||||||
|
// 13. RESPONSIVE UTILITIES
|
||||||
|
// ========================================
|
||||||
|
|
||||||
|
@mixin responsive($breakpoint) {
|
||||||
|
@media (min-width: $breakpoint) {
|
||||||
|
@content;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Usage: @include responsive($breakpoint-md) { ... }
|
||||||
|
|
||||||
|
// ========================================
|
||||||
|
// 14. DARK MODE SUPPORT
|
||||||
|
// ========================================
|
||||||
|
|
||||||
|
@mixin dark-mode {
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
@content;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] & {
|
||||||
|
@content;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,721 @@
|
||||||
|
<template>
|
||||||
|
<div class="admin-dashboard-v2">
|
||||||
|
<!-- Neumorphic Header -->
|
||||||
|
<div class="dashboard-header">
|
||||||
|
<h1 class="dashboard-title">System Administration</h1>
|
||||||
|
<p class="dashboard-subtitle">Complete platform control and management</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Stats Grid with Neumorphic Cards -->
|
||||||
|
<div class="stats-grid">
|
||||||
|
<div class="stat-card neumorphic-card" v-for="stat in stats" :key="stat.id">
|
||||||
|
<div class="stat-content">
|
||||||
|
<div class="stat-info">
|
||||||
|
<div class="stat-label">{{ stat.label }}</div>
|
||||||
|
<div class="stat-value">{{ stat.value }}</div>
|
||||||
|
<div class="stat-change" :class="stat.changeType">
|
||||||
|
<Icon :name="stat.changeIcon" class="change-icon" />
|
||||||
|
<span>{{ stat.changeText }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-icon-wrapper neumorphic-inset">
|
||||||
|
<Icon :name="stat.icon" class="stat-icon" :style="{ color: stat.color }" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Main Management Sections -->
|
||||||
|
<div class="management-grid">
|
||||||
|
<!-- User Management -->
|
||||||
|
<div class="management-card neumorphic-card">
|
||||||
|
<div class="card-header">
|
||||||
|
<Icon name="mdi:account-group" class="header-icon" />
|
||||||
|
<h2>User Management</h2>
|
||||||
|
</div>
|
||||||
|
<p class="card-description">Manage user accounts, roles, and permissions</p>
|
||||||
|
|
||||||
|
<!-- Morphing Dropdown for User Filters -->
|
||||||
|
<div class="morphing-select-wrapper">
|
||||||
|
<div class="select-trigger neumorphic-button" @click="toggleUserFilter">
|
||||||
|
<span>{{ selectedUserFilter }}</span>
|
||||||
|
<Icon name="mdi:chevron-down" class="dropdown-icon" :class="{ 'rotate': showUserFilter }" />
|
||||||
|
</div>
|
||||||
|
<Transition name="morph">
|
||||||
|
<div v-if="showUserFilter" class="morphing-dropdown">
|
||||||
|
<div
|
||||||
|
v-for="option in userFilterOptions"
|
||||||
|
:key="option"
|
||||||
|
class="dropdown-option"
|
||||||
|
@click="selectUserFilter(option)"
|
||||||
|
>
|
||||||
|
{{ option }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Transition>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="action-buttons">
|
||||||
|
<button class="neumorphic-button primary" @click="showCreateUserDialog = true">
|
||||||
|
<Icon name="mdi:account-plus" />
|
||||||
|
Create User
|
||||||
|
</button>
|
||||||
|
<button class="neumorphic-button" @click="manageRoles">
|
||||||
|
<Icon name="mdi:shield-account" />
|
||||||
|
Manage Roles
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- System Maintenance -->
|
||||||
|
<div class="management-card neumorphic-card">
|
||||||
|
<div class="card-header">
|
||||||
|
<Icon name="mdi:cog" class="header-icon" />
|
||||||
|
<h2>System Maintenance</h2>
|
||||||
|
</div>
|
||||||
|
<p class="card-description">Backend operations and system health</p>
|
||||||
|
|
||||||
|
<!-- System Status Indicator -->
|
||||||
|
<div class="system-status neumorphic-inset">
|
||||||
|
<div class="status-indicator" :class="systemStatus.type"></div>
|
||||||
|
<span>{{ systemStatus.text }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="action-buttons">
|
||||||
|
<button class="neumorphic-button" @click="assignMemberIds">
|
||||||
|
Assign Member IDs
|
||||||
|
</button>
|
||||||
|
<button class="neumorphic-button" @click="backfillEventIds">
|
||||||
|
Backfill Event IDs
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Reports & Analytics -->
|
||||||
|
<div class="management-card neumorphic-card">
|
||||||
|
<div class="card-header">
|
||||||
|
<Icon name="mdi:chart-line" class="header-icon" />
|
||||||
|
<h2>Reports & Analytics</h2>
|
||||||
|
</div>
|
||||||
|
<p class="card-description">Generate insights and track metrics</p>
|
||||||
|
|
||||||
|
<!-- Report Type Dropdown -->
|
||||||
|
<div class="morphing-select-wrapper">
|
||||||
|
<div class="select-trigger neumorphic-button" @click="toggleReportType">
|
||||||
|
<span>{{ selectedReportType }}</span>
|
||||||
|
<Icon name="mdi:chevron-down" class="dropdown-icon" :class="{ 'rotate': showReportType }" />
|
||||||
|
</div>
|
||||||
|
<Transition name="morph">
|
||||||
|
<div v-if="showReportType" class="morphing-dropdown">
|
||||||
|
<div
|
||||||
|
v-for="type in reportTypes"
|
||||||
|
:key="type"
|
||||||
|
class="dropdown-option"
|
||||||
|
@click="selectReportType(type)"
|
||||||
|
>
|
||||||
|
{{ type }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Transition>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button class="neumorphic-button primary full-width" @click="generateReport">
|
||||||
|
<Icon name="mdi:file-chart" />
|
||||||
|
Generate Report
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Configuration -->
|
||||||
|
<div class="management-card neumorphic-card">
|
||||||
|
<div class="card-header">
|
||||||
|
<Icon name="mdi:tune" class="header-icon" />
|
||||||
|
<h2>Configuration</h2>
|
||||||
|
</div>
|
||||||
|
<p class="card-description">Portal settings and integrations</p>
|
||||||
|
|
||||||
|
<div class="config-grid">
|
||||||
|
<button class="config-button neumorphic-button" @click="showMembershipConfig = true">
|
||||||
|
<Icon name="mdi:card-account-details" />
|
||||||
|
<span>Membership</span>
|
||||||
|
</button>
|
||||||
|
<button class="config-button neumorphic-button" @click="showRecaptchaConfig = true">
|
||||||
|
<Icon name="mdi:robot" />
|
||||||
|
<span>reCAPTCHA</span>
|
||||||
|
</button>
|
||||||
|
<button class="config-button neumorphic-button" @click="openEmailConfig">
|
||||||
|
<Icon name="mdi:email" />
|
||||||
|
<span>Email</span>
|
||||||
|
</button>
|
||||||
|
<button class="config-button neumorphic-button" @click="showNocoDBSettings = true">
|
||||||
|
<Icon name="mdi:database" />
|
||||||
|
<span>Database</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Activity Feed -->
|
||||||
|
<div class="activity-section neumorphic-card">
|
||||||
|
<div class="card-header">
|
||||||
|
<Icon name="mdi:timeline" class="header-icon" />
|
||||||
|
<h2>Recent Activity</h2>
|
||||||
|
<button class="neumorphic-button small" @click="refreshActivity">
|
||||||
|
<Icon name="mdi:refresh" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="activity-list">
|
||||||
|
<div v-for="activity in recentActivity" :key="activity.id" class="activity-item neumorphic-inset">
|
||||||
|
<Icon :name="activity.icon" class="activity-icon" :style="{ color: activity.color }" />
|
||||||
|
<div class="activity-content">
|
||||||
|
<p class="activity-text">{{ activity.text }}</p>
|
||||||
|
<span class="activity-time">{{ activity.time }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, computed, onMounted } from 'vue'
|
||||||
|
|
||||||
|
// Define page meta
|
||||||
|
definePageMeta({
|
||||||
|
layout: 'admin',
|
||||||
|
middleware: 'auth'
|
||||||
|
})
|
||||||
|
|
||||||
|
// Stats data
|
||||||
|
const stats = ref([
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
label: 'Total Members',
|
||||||
|
value: '1,247',
|
||||||
|
changeType: 'positive',
|
||||||
|
changeIcon: 'mdi:trending-up',
|
||||||
|
changeText: '+12% this month',
|
||||||
|
icon: 'mdi:account-group',
|
||||||
|
color: '#CC0000'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
label: 'Active Sessions',
|
||||||
|
value: '342',
|
||||||
|
changeType: 'neutral',
|
||||||
|
changeIcon: 'mdi:circle',
|
||||||
|
changeText: 'Live now',
|
||||||
|
icon: 'mdi:monitor-dashboard',
|
||||||
|
color: '#10B981'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
label: 'Revenue MTD',
|
||||||
|
value: '$48,392',
|
||||||
|
changeType: 'positive',
|
||||||
|
changeIcon: 'mdi:trending-up',
|
||||||
|
changeText: '+8% vs last month',
|
||||||
|
icon: 'mdi:currency-usd',
|
||||||
|
color: '#3B82F6'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
label: 'System Health',
|
||||||
|
value: '98.5%',
|
||||||
|
changeType: 'positive',
|
||||||
|
changeIcon: 'mdi:check-circle',
|
||||||
|
changeText: 'All systems operational',
|
||||||
|
icon: 'mdi:shield-check',
|
||||||
|
color: '#10B981'
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
// Dropdown states
|
||||||
|
const showUserFilter = ref(false)
|
||||||
|
const selectedUserFilter = ref('All Users')
|
||||||
|
const userFilterOptions = ref(['All Users', 'Active Users', 'Inactive Users', 'Admins', 'Members'])
|
||||||
|
|
||||||
|
const showReportType = ref(false)
|
||||||
|
const selectedReportType = ref('Financial Report')
|
||||||
|
const reportTypes = ref(['Financial Report', 'Member Report', 'Activity Report', 'Usage Report'])
|
||||||
|
|
||||||
|
// System status
|
||||||
|
const systemStatus = ref({
|
||||||
|
type: 'healthy',
|
||||||
|
text: 'All systems operational'
|
||||||
|
})
|
||||||
|
|
||||||
|
// Recent activity
|
||||||
|
const recentActivity = ref([
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
icon: 'mdi:account-plus',
|
||||||
|
text: 'New member registration: John Doe',
|
||||||
|
time: '2 minutes ago',
|
||||||
|
color: '#10B981'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
icon: 'mdi:credit-card',
|
||||||
|
text: 'Payment received from Jane Smith',
|
||||||
|
time: '15 minutes ago',
|
||||||
|
color: '#3B82F6'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
icon: 'mdi:calendar-check',
|
||||||
|
text: 'Event created: Annual Gala 2024',
|
||||||
|
time: '1 hour ago',
|
||||||
|
color: '#F59E0B'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
icon: 'mdi:account-edit',
|
||||||
|
text: 'Profile updated: Mike Johnson',
|
||||||
|
time: '3 hours ago',
|
||||||
|
color: '#6B7280'
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
// Dialog states
|
||||||
|
const showCreateUserDialog = ref(false)
|
||||||
|
const showMembershipConfig = ref(false)
|
||||||
|
const showRecaptchaConfig = ref(false)
|
||||||
|
const showNocoDBSettings = ref(false)
|
||||||
|
|
||||||
|
// Methods
|
||||||
|
const toggleUserFilter = () => {
|
||||||
|
showUserFilter.value = !showUserFilter.value
|
||||||
|
showReportType.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const selectUserFilter = (option) => {
|
||||||
|
selectedUserFilter.value = option
|
||||||
|
showUserFilter.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const toggleReportType = () => {
|
||||||
|
showReportType.value = !showReportType.value
|
||||||
|
showUserFilter.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const selectReportType = (type) => {
|
||||||
|
selectedReportType.value = type
|
||||||
|
showReportType.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const manageRoles = () => {
|
||||||
|
console.log('Managing roles...')
|
||||||
|
}
|
||||||
|
|
||||||
|
const assignMemberIds = () => {
|
||||||
|
console.log('Assigning member IDs...')
|
||||||
|
}
|
||||||
|
|
||||||
|
const backfillEventIds = () => {
|
||||||
|
console.log('Backfilling event IDs...')
|
||||||
|
}
|
||||||
|
|
||||||
|
const generateReport = () => {
|
||||||
|
console.log('Generating report:', selectedReportType.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
const openEmailConfig = () => {
|
||||||
|
console.log('Opening email configuration...')
|
||||||
|
}
|
||||||
|
|
||||||
|
const refreshActivity = () => {
|
||||||
|
console.log('Refreshing activity...')
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
// Close dropdowns when clicking outside
|
||||||
|
document.addEventListener('click', (e) => {
|
||||||
|
if (!e.target.closest('.morphing-select-wrapper')) {
|
||||||
|
showUserFilter.value = false
|
||||||
|
showReportType.value = false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import '@/design-mockups/styles/design-system.scss';
|
||||||
|
|
||||||
|
.admin-dashboard-v2 {
|
||||||
|
padding: 2rem;
|
||||||
|
background: linear-gradient(135deg, $neutral-50 0%, $neutral-100 100%);
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Header
|
||||||
|
.dashboard-header {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 3rem;
|
||||||
|
|
||||||
|
.dashboard-title {
|
||||||
|
font-size: $text-4xl;
|
||||||
|
font-weight: $font-bold;
|
||||||
|
color: $neutral-800;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
background: linear-gradient(135deg, $primary-600, $primary-800);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
background-clip: text;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboard-subtitle {
|
||||||
|
color: $neutral-600;
|
||||||
|
font-size: $text-lg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stats Grid
|
||||||
|
.stats-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
||||||
|
gap: 1.5rem;
|
||||||
|
margin-bottom: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-card {
|
||||||
|
@include neumorphic-card('md');
|
||||||
|
padding: 1.5rem;
|
||||||
|
transition: all $transition-base;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
@include neumorphic-card('lg');
|
||||||
|
transform: translateY(-2px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-content {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-info {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-label {
|
||||||
|
color: $neutral-600;
|
||||||
|
font-size: $text-sm;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-value {
|
||||||
|
font-size: $text-3xl;
|
||||||
|
font-weight: $font-bold;
|
||||||
|
color: $neutral-800;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-change {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.25rem;
|
||||||
|
font-size: $text-sm;
|
||||||
|
|
||||||
|
&.positive {
|
||||||
|
color: $success-500;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.neutral {
|
||||||
|
color: $neutral-600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.change-icon {
|
||||||
|
width: 14px;
|
||||||
|
height: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-icon-wrapper {
|
||||||
|
width: 60px;
|
||||||
|
height: 60px;
|
||||||
|
border-radius: $radius-xl;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
box-shadow: $shadow-inset-sm;
|
||||||
|
|
||||||
|
.stat-icon {
|
||||||
|
width: 28px;
|
||||||
|
height: 28px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Management Grid
|
||||||
|
.management-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
|
||||||
|
gap: 2rem;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.management-card {
|
||||||
|
@include neumorphic-card('md');
|
||||||
|
padding: 2rem;
|
||||||
|
|
||||||
|
.card-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.75rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
|
||||||
|
.header-icon {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
color: $primary-600;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: $text-xl;
|
||||||
|
font-weight: $font-semibold;
|
||||||
|
color: $neutral-800;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-description {
|
||||||
|
color: $neutral-600;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
font-size: $text-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-buttons {
|
||||||
|
display: flex;
|
||||||
|
gap: 1rem;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-button {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
padding: 1rem;
|
||||||
|
font-size: $text-sm;
|
||||||
|
|
||||||
|
svg {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Morphing Dropdown
|
||||||
|
.morphing-select-wrapper {
|
||||||
|
position: relative;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
|
||||||
|
.select-trigger {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
.dropdown-icon {
|
||||||
|
transition: transform 0.3s $spring-smooth;
|
||||||
|
|
||||||
|
&.rotate {
|
||||||
|
transform: rotate(180deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.morphing-dropdown {
|
||||||
|
@include morphing-dropdown();
|
||||||
|
position: absolute;
|
||||||
|
top: calc(100% + 8px);
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: $z-dropdown;
|
||||||
|
|
||||||
|
.dropdown-option {
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all $transition-fast;
|
||||||
|
color: $neutral-700;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: rgba($blue-500, 0.1);
|
||||||
|
color: $blue-600;
|
||||||
|
padding-left: 1.25rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Neumorphic Elements
|
||||||
|
.neumorphic-card {
|
||||||
|
background: linear-gradient(145deg, #ffffff, #f0f0f0);
|
||||||
|
border-radius: $radius-xl;
|
||||||
|
box-shadow: $shadow-soft-md;
|
||||||
|
}
|
||||||
|
|
||||||
|
.neumorphic-button {
|
||||||
|
@include neumorphic-button();
|
||||||
|
padding: 0.75rem 1.5rem;
|
||||||
|
border: none;
|
||||||
|
border-radius: $radius-lg;
|
||||||
|
font-weight: $font-medium;
|
||||||
|
color: $neutral-700;
|
||||||
|
cursor: pointer;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
|
||||||
|
&.primary {
|
||||||
|
background: linear-gradient(145deg, $primary-600, $primary-700);
|
||||||
|
color: white;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: linear-gradient(145deg, $primary-700, $primary-800);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.small {
|
||||||
|
padding: 0.5rem 0.75rem;
|
||||||
|
font-size: $text-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.full-width {
|
||||||
|
width: 100%;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg {
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.neumorphic-inset {
|
||||||
|
box-shadow: $shadow-inset-sm;
|
||||||
|
background: linear-gradient(145deg, #e6e6e6, #ffffff);
|
||||||
|
}
|
||||||
|
|
||||||
|
// System Status
|
||||||
|
.system-status {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.75rem;
|
||||||
|
padding: 1rem;
|
||||||
|
border-radius: $radius-lg;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
|
||||||
|
.status-indicator {
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
border-radius: 50%;
|
||||||
|
animation: pulse 2s infinite;
|
||||||
|
|
||||||
|
&.healthy {
|
||||||
|
background-color: $success-500;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.warning {
|
||||||
|
background-color: $warning-500;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.error {
|
||||||
|
background-color: $error-500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Activity Section
|
||||||
|
.activity-section {
|
||||||
|
@include neumorphic-card('lg');
|
||||||
|
padding: 2rem;
|
||||||
|
|
||||||
|
.card-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.75rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.activity-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.activity-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 1rem;
|
||||||
|
padding: 1rem;
|
||||||
|
border-radius: $radius-lg;
|
||||||
|
|
||||||
|
.activity-icon {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.activity-content {
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
.activity-text {
|
||||||
|
color: $neutral-800;
|
||||||
|
font-size: $text-sm;
|
||||||
|
margin-bottom: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.activity-time {
|
||||||
|
color: $neutral-500;
|
||||||
|
font-size: $text-xs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transitions
|
||||||
|
.morph-enter-active,
|
||||||
|
.morph-leave-active {
|
||||||
|
transition: all 0.3s $spring-smooth;
|
||||||
|
}
|
||||||
|
|
||||||
|
.morph-enter-from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: scale(0.95) translateY(-10px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.morph-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
transform: scale(0.95) translateY(-10px);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Responsive
|
||||||
|
@include responsive($breakpoint-md) {
|
||||||
|
.admin-dashboard-v2 {
|
||||||
|
padding: 3rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include responsive($breakpoint-lg) {
|
||||||
|
.stats-grid {
|
||||||
|
grid-template-columns: repeat(4, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
|
.management-grid {
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,886 @@
|
||||||
|
<template>
|
||||||
|
<div class="board-dashboard-v2">
|
||||||
|
<!-- Executive Header -->
|
||||||
|
<div class="executive-header">
|
||||||
|
<h1 class="dashboard-title">Executive Dashboard</h1>
|
||||||
|
<p class="dashboard-subtitle">Strategic insights and governance overview</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- KPI Cards with Neumorphic Design -->
|
||||||
|
<div class="kpi-grid">
|
||||||
|
<div class="kpi-card neumorphic-card" v-for="kpi in kpis" :key="kpi.id">
|
||||||
|
<div class="kpi-header">
|
||||||
|
<div class="kpi-icon-wrapper neumorphic-inset">
|
||||||
|
<Icon :name="kpi.icon" class="kpi-icon" :style="{ color: kpi.color }" />
|
||||||
|
</div>
|
||||||
|
<div class="kpi-trend" :class="kpi.trendType">
|
||||||
|
<Icon :name="kpi.trendIcon" class="trend-icon" />
|
||||||
|
<span>{{ kpi.trendValue }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="kpi-content">
|
||||||
|
<div class="kpi-value">{{ kpi.value }}</div>
|
||||||
|
<div class="kpi-label">{{ kpi.label }}</div>
|
||||||
|
<div class="kpi-progress">
|
||||||
|
<div class="progress-bar neumorphic-inset">
|
||||||
|
<div class="progress-fill" :style="{ width: kpi.progress + '%', background: kpi.color }"></div>
|
||||||
|
</div>
|
||||||
|
<span class="progress-text">{{ kpi.progress }}% of target</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Strategic Initiatives & Governance -->
|
||||||
|
<div class="governance-grid">
|
||||||
|
<!-- Strategic Initiatives -->
|
||||||
|
<div class="initiative-card neumorphic-card">
|
||||||
|
<div class="card-header">
|
||||||
|
<Icon name="mdi:target" class="header-icon" />
|
||||||
|
<h2>Strategic Initiatives</h2>
|
||||||
|
<div class="morphing-select-wrapper">
|
||||||
|
<button class="select-trigger neumorphic-button small" @click="toggleQuarter">
|
||||||
|
<span>{{ selectedQuarter }}</span>
|
||||||
|
<Icon name="mdi:chevron-down" class="dropdown-icon" :class="{ 'rotate': showQuarter }" />
|
||||||
|
</button>
|
||||||
|
<Transition name="morph">
|
||||||
|
<div v-if="showQuarter" class="morphing-dropdown">
|
||||||
|
<div
|
||||||
|
v-for="quarter in quarters"
|
||||||
|
:key="quarter"
|
||||||
|
class="dropdown-option"
|
||||||
|
@click="selectQuarter(quarter)"
|
||||||
|
>
|
||||||
|
{{ quarter }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Transition>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="initiatives-list">
|
||||||
|
<div v-for="initiative in strategicInitiatives" :key="initiative.id" class="initiative-item">
|
||||||
|
<div class="initiative-header">
|
||||||
|
<span class="initiative-name">{{ initiative.name }}</span>
|
||||||
|
<span class="initiative-status" :class="initiative.status">{{ initiative.statusText }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="initiative-progress neumorphic-inset">
|
||||||
|
<div class="progress-bar-slim">
|
||||||
|
<div class="progress-fill-slim" :style="{ width: initiative.progress + '%' }"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="initiative-meta">
|
||||||
|
<span class="initiative-owner">Owner: {{ initiative.owner }}</span>
|
||||||
|
<span class="initiative-deadline">Due: {{ initiative.deadline }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Committee Overview -->
|
||||||
|
<div class="committee-card neumorphic-card">
|
||||||
|
<div class="card-header">
|
||||||
|
<Icon name="mdi:account-group-outline" class="header-icon" />
|
||||||
|
<h2>Committee Activities</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="committee-grid">
|
||||||
|
<div v-for="committee in committees" :key="committee.id" class="committee-item neumorphic-inset">
|
||||||
|
<div class="committee-header">
|
||||||
|
<Icon :name="committee.icon" class="committee-icon" :style="{ color: committee.color }" />
|
||||||
|
<h3>{{ committee.name }}</h3>
|
||||||
|
</div>
|
||||||
|
<div class="committee-stats">
|
||||||
|
<div class="stat">
|
||||||
|
<span class="stat-value">{{ committee.members }}</span>
|
||||||
|
<span class="stat-label">Members</span>
|
||||||
|
</div>
|
||||||
|
<div class="stat">
|
||||||
|
<span class="stat-value">{{ committee.meetings }}</span>
|
||||||
|
<span class="stat-label">Meetings</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button class="neumorphic-button small full-width">View Details</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Financial Overview -->
|
||||||
|
<div class="financial-section neumorphic-card">
|
||||||
|
<div class="card-header">
|
||||||
|
<Icon name="mdi:finance" class="header-icon" />
|
||||||
|
<h2>Financial Overview</h2>
|
||||||
|
<div class="time-selector">
|
||||||
|
<button
|
||||||
|
v-for="period in timePeriods"
|
||||||
|
:key="period"
|
||||||
|
class="time-button neumorphic-button small"
|
||||||
|
:class="{ 'active': selectedPeriod === period }"
|
||||||
|
@click="selectedPeriod = period"
|
||||||
|
>
|
||||||
|
{{ period }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="financial-grid">
|
||||||
|
<div class="revenue-chart">
|
||||||
|
<h3>Revenue Trend</h3>
|
||||||
|
<div class="chart-placeholder neumorphic-inset">
|
||||||
|
<Icon name="mdi:chart-line" class="chart-icon" />
|
||||||
|
<span>Revenue chart visualization</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="financial-metrics">
|
||||||
|
<div v-for="metric in financialMetrics" :key="metric.id" class="metric-item">
|
||||||
|
<div class="metric-label">{{ metric.label }}</div>
|
||||||
|
<div class="metric-value" :class="metric.type">{{ metric.value }}</div>
|
||||||
|
<div class="metric-change">
|
||||||
|
<Icon :name="metric.changeIcon" class="change-icon" />
|
||||||
|
<span>{{ metric.change }} from last period</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Governance Actions -->
|
||||||
|
<div class="governance-actions">
|
||||||
|
<div class="action-card neumorphic-card">
|
||||||
|
<Icon name="mdi:calendar-check" class="action-icon" />
|
||||||
|
<h3>Board Meetings</h3>
|
||||||
|
<p>Schedule and manage board meetings</p>
|
||||||
|
<button class="neumorphic-button primary">Schedule Meeting</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="action-card neumorphic-card">
|
||||||
|
<Icon name="mdi:file-document-outline" class="action-icon" />
|
||||||
|
<h3>Documents</h3>
|
||||||
|
<p>Access governance documents</p>
|
||||||
|
<button class="neumorphic-button primary">View Documents</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="action-card neumorphic-card">
|
||||||
|
<Icon name="mdi:vote" class="action-icon" />
|
||||||
|
<h3>Resolutions</h3>
|
||||||
|
<p>Review and vote on resolutions</p>
|
||||||
|
<button class="neumorphic-button primary">View Resolutions</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="action-card neumorphic-card">
|
||||||
|
<Icon name="mdi:chart-box-outline" class="action-icon" />
|
||||||
|
<h3>Reports</h3>
|
||||||
|
<p>Generate executive reports</p>
|
||||||
|
<button class="neumorphic-button primary">Generate Report</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, onMounted } from 'vue'
|
||||||
|
|
||||||
|
// Define page meta
|
||||||
|
definePageMeta({
|
||||||
|
layout: 'board',
|
||||||
|
middleware: 'auth'
|
||||||
|
})
|
||||||
|
|
||||||
|
// KPIs
|
||||||
|
const kpis = ref([
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
label: 'Member Growth',
|
||||||
|
value: '24.8%',
|
||||||
|
icon: 'mdi:account-multiple-plus',
|
||||||
|
color: '#10B981',
|
||||||
|
trendType: 'positive',
|
||||||
|
trendIcon: 'mdi:trending-up',
|
||||||
|
trendValue: '+5.2%',
|
||||||
|
progress: 82
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
label: 'Revenue YTD',
|
||||||
|
value: '$2.4M',
|
||||||
|
icon: 'mdi:cash-multiple',
|
||||||
|
color: '#3B82F6',
|
||||||
|
trendType: 'positive',
|
||||||
|
trendIcon: 'mdi:trending-up',
|
||||||
|
trendValue: '+12.3%',
|
||||||
|
progress: 68
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
label: 'Member Retention',
|
||||||
|
value: '94.5%',
|
||||||
|
icon: 'mdi:account-heart',
|
||||||
|
color: '#CC0000',
|
||||||
|
trendType: 'positive',
|
||||||
|
trendIcon: 'mdi:trending-up',
|
||||||
|
trendValue: '+2.1%',
|
||||||
|
progress: 95
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
label: 'NPS Score',
|
||||||
|
value: '72',
|
||||||
|
icon: 'mdi:emoticon-happy',
|
||||||
|
color: '#F59E0B',
|
||||||
|
trendType: 'neutral',
|
||||||
|
trendIcon: 'mdi:minus',
|
||||||
|
trendValue: '0%',
|
||||||
|
progress: 72
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
// Strategic Initiatives
|
||||||
|
const strategicInitiatives = ref([
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: 'Digital Transformation Initiative',
|
||||||
|
status: 'on-track',
|
||||||
|
statusText: 'On Track',
|
||||||
|
progress: 65,
|
||||||
|
owner: 'John Smith',
|
||||||
|
deadline: 'Q2 2024'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: 'Member Experience Enhancement',
|
||||||
|
status: 'ahead',
|
||||||
|
statusText: 'Ahead',
|
||||||
|
progress: 78,
|
||||||
|
owner: 'Sarah Johnson',
|
||||||
|
deadline: 'Q1 2024'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
name: 'International Expansion',
|
||||||
|
status: 'at-risk',
|
||||||
|
statusText: 'At Risk',
|
||||||
|
progress: 42,
|
||||||
|
owner: 'Mike Chen',
|
||||||
|
deadline: 'Q3 2024'
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
// Committees
|
||||||
|
const committees = ref([
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: 'Finance',
|
||||||
|
icon: 'mdi:calculator',
|
||||||
|
color: '#3B82F6',
|
||||||
|
members: 7,
|
||||||
|
meetings: 12
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: 'Governance',
|
||||||
|
icon: 'mdi:gavel',
|
||||||
|
color: '#CC0000',
|
||||||
|
members: 5,
|
||||||
|
meetings: 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
name: 'Audit',
|
||||||
|
icon: 'mdi:magnify',
|
||||||
|
color: '#F59E0B',
|
||||||
|
members: 4,
|
||||||
|
meetings: 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
name: 'Compensation',
|
||||||
|
icon: 'mdi:cash',
|
||||||
|
color: '#10B981',
|
||||||
|
members: 6,
|
||||||
|
meetings: 6
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
// Financial Metrics
|
||||||
|
const financialMetrics = ref([
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
label: 'Total Revenue',
|
||||||
|
value: '$2.4M',
|
||||||
|
type: 'positive',
|
||||||
|
changeIcon: 'mdi:arrow-up',
|
||||||
|
change: '+12.3%'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
label: 'Operating Expenses',
|
||||||
|
value: '$1.8M',
|
||||||
|
type: 'neutral',
|
||||||
|
changeIcon: 'mdi:arrow-up',
|
||||||
|
change: '+8.1%'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
label: 'Net Profit',
|
||||||
|
value: '$620K',
|
||||||
|
type: 'positive',
|
||||||
|
changeIcon: 'mdi:arrow-up',
|
||||||
|
change: '+24.5%'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
label: 'Cash Flow',
|
||||||
|
value: '$450K',
|
||||||
|
type: 'positive',
|
||||||
|
changeIcon: 'mdi:arrow-up',
|
||||||
|
change: '+15.2%'
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
// Dropdown states
|
||||||
|
const showQuarter = ref(false)
|
||||||
|
const selectedQuarter = ref('Q4 2023')
|
||||||
|
const quarters = ref(['Q1 2023', 'Q2 2023', 'Q3 2023', 'Q4 2023', 'Q1 2024'])
|
||||||
|
|
||||||
|
// Time period selector
|
||||||
|
const selectedPeriod = ref('YTD')
|
||||||
|
const timePeriods = ref(['MTD', 'QTD', 'YTD'])
|
||||||
|
|
||||||
|
// Methods
|
||||||
|
const toggleQuarter = () => {
|
||||||
|
showQuarter.value = !showQuarter.value
|
||||||
|
}
|
||||||
|
|
||||||
|
const selectQuarter = (quarter) => {
|
||||||
|
selectedQuarter.value = quarter
|
||||||
|
showQuarter.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
// Close dropdown when clicking outside
|
||||||
|
document.addEventListener('click', (e) => {
|
||||||
|
if (!e.target.closest('.morphing-select-wrapper')) {
|
||||||
|
showQuarter.value = false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import '@/design-mockups/styles/design-system.scss';
|
||||||
|
|
||||||
|
.board-dashboard-v2 {
|
||||||
|
padding: 2rem;
|
||||||
|
background: linear-gradient(135deg, $neutral-50 0%, $neutral-100 100%);
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Executive Header
|
||||||
|
.executive-header {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 3rem;
|
||||||
|
|
||||||
|
.dashboard-title {
|
||||||
|
font-size: $text-4xl;
|
||||||
|
font-weight: $font-bold;
|
||||||
|
background: linear-gradient(135deg, $primary-600, $primary-800);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
background-clip: text;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboard-subtitle {
|
||||||
|
color: $neutral-600;
|
||||||
|
font-size: $text-lg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// KPI Grid
|
||||||
|
.kpi-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
||||||
|
gap: 1.5rem;
|
||||||
|
margin-bottom: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kpi-card {
|
||||||
|
@include neumorphic-card('md');
|
||||||
|
padding: 1.5rem;
|
||||||
|
|
||||||
|
.kpi-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kpi-icon-wrapper {
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
border-radius: $radius-lg;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
box-shadow: $shadow-inset-sm;
|
||||||
|
|
||||||
|
.kpi-icon {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.kpi-trend {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.25rem;
|
||||||
|
font-size: $text-sm;
|
||||||
|
font-weight: $font-semibold;
|
||||||
|
|
||||||
|
&.positive { color: $success-500; }
|
||||||
|
&.negative { color: $error-500; }
|
||||||
|
&.neutral { color: $neutral-600; }
|
||||||
|
|
||||||
|
.trend-icon {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.kpi-value {
|
||||||
|
font-size: $text-3xl;
|
||||||
|
font-weight: $font-bold;
|
||||||
|
color: $neutral-800;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kpi-label {
|
||||||
|
color: $neutral-600;
|
||||||
|
font-size: $text-sm;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kpi-progress {
|
||||||
|
.progress-bar {
|
||||||
|
height: 8px;
|
||||||
|
border-radius: $radius-full;
|
||||||
|
overflow: hidden;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
|
||||||
|
.progress-fill {
|
||||||
|
height: 100%;
|
||||||
|
border-radius: $radius-full;
|
||||||
|
transition: width 0.5s $spring-smooth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-text {
|
||||||
|
font-size: $text-xs;
|
||||||
|
color: $neutral-500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Governance Grid
|
||||||
|
.governance-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 2rem;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
|
||||||
|
@media (max-width: $breakpoint-lg) {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.initiative-card,
|
||||||
|
.committee-card {
|
||||||
|
@include neumorphic-card('md');
|
||||||
|
padding: 2rem;
|
||||||
|
|
||||||
|
.card-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.75rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.header-icon {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
color: $primary-600;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: $text-xl;
|
||||||
|
font-weight: $font-semibold;
|
||||||
|
color: $neutral-800;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Strategic Initiatives
|
||||||
|
.initiatives-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.initiative-item {
|
||||||
|
padding: 1rem;
|
||||||
|
border-radius: $radius-lg;
|
||||||
|
background: $neutral-50;
|
||||||
|
|
||||||
|
.initiative-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.initiative-name {
|
||||||
|
font-weight: $font-medium;
|
||||||
|
color: $neutral-800;
|
||||||
|
font-size: $text-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.initiative-status {
|
||||||
|
padding: 0.25rem 0.75rem;
|
||||||
|
border-radius: $radius-full;
|
||||||
|
font-size: $text-xs;
|
||||||
|
font-weight: $font-medium;
|
||||||
|
|
||||||
|
&.on-track {
|
||||||
|
background: rgba($success-500, 0.1);
|
||||||
|
color: $success-500;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.ahead {
|
||||||
|
background: rgba($blue-500, 0.1);
|
||||||
|
color: $blue-500;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.at-risk {
|
||||||
|
background: rgba($warning-500, 0.1);
|
||||||
|
color: $warning-500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.initiative-progress {
|
||||||
|
margin-bottom: 0.75rem;
|
||||||
|
padding: 0.25rem;
|
||||||
|
border-radius: $radius-full;
|
||||||
|
|
||||||
|
.progress-bar-slim {
|
||||||
|
height: 4px;
|
||||||
|
border-radius: $radius-full;
|
||||||
|
background: rgba($neutral-300, 0.3);
|
||||||
|
|
||||||
|
.progress-fill-slim {
|
||||||
|
height: 100%;
|
||||||
|
background: linear-gradient(135deg, $primary-600, $primary-700);
|
||||||
|
border-radius: $radius-full;
|
||||||
|
transition: width 0.5s $spring-smooth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.initiative-meta {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
font-size: $text-xs;
|
||||||
|
color: $neutral-600;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Committee Grid
|
||||||
|
.committee-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.committee-item {
|
||||||
|
padding: 1rem;
|
||||||
|
border-radius: $radius-lg;
|
||||||
|
|
||||||
|
.committee-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
|
||||||
|
.committee-icon {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: $text-sm;
|
||||||
|
font-weight: $font-semibold;
|
||||||
|
color: $neutral-800;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.committee-stats {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
|
||||||
|
.stat {
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
.stat-value {
|
||||||
|
display: block;
|
||||||
|
font-size: $text-xl;
|
||||||
|
font-weight: $font-bold;
|
||||||
|
color: $neutral-800;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-label {
|
||||||
|
font-size: $text-xs;
|
||||||
|
color: $neutral-600;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Financial Section
|
||||||
|
.financial-section {
|
||||||
|
@include neumorphic-card('lg');
|
||||||
|
padding: 2rem;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
|
||||||
|
.time-selector {
|
||||||
|
display: flex;
|
||||||
|
gap: 0.5rem;
|
||||||
|
|
||||||
|
.time-button {
|
||||||
|
&.active {
|
||||||
|
background: linear-gradient(145deg, $primary-600, $primary-700);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.financial-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 2rem;
|
||||||
|
|
||||||
|
@media (max-width: $breakpoint-md) {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.revenue-chart {
|
||||||
|
h3 {
|
||||||
|
font-size: $text-lg;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
color: $neutral-800;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-placeholder {
|
||||||
|
height: 200px;
|
||||||
|
border-radius: $radius-lg;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
color: $neutral-500;
|
||||||
|
|
||||||
|
.chart-icon {
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.financial-metrics {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.metric-item {
|
||||||
|
padding: 1rem;
|
||||||
|
|
||||||
|
.metric-label {
|
||||||
|
font-size: $text-xs;
|
||||||
|
color: $neutral-600;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.metric-value {
|
||||||
|
font-size: $text-xl;
|
||||||
|
font-weight: $font-bold;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
|
||||||
|
&.positive { color: $success-500; }
|
||||||
|
&.negative { color: $error-500; }
|
||||||
|
&.neutral { color: $neutral-800; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.metric-change {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.25rem;
|
||||||
|
font-size: $text-xs;
|
||||||
|
color: $neutral-600;
|
||||||
|
|
||||||
|
.change-icon {
|
||||||
|
width: 14px;
|
||||||
|
height: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Governance Actions
|
||||||
|
.governance-actions {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||||
|
gap: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-card {
|
||||||
|
@include neumorphic-card('md');
|
||||||
|
padding: 2rem;
|
||||||
|
text-align: center;
|
||||||
|
transition: all $transition-base;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
@include neumorphic-card('lg');
|
||||||
|
transform: translateY(-2px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-icon {
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
color: $primary-600;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: $text-lg;
|
||||||
|
font-weight: $font-semibold;
|
||||||
|
color: $neutral-800;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
color: $neutral-600;
|
||||||
|
font-size: $text-sm;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Morphing Dropdown
|
||||||
|
.morphing-select-wrapper {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.select-trigger {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
|
||||||
|
.dropdown-icon {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
transition: transform 0.3s $spring-smooth;
|
||||||
|
|
||||||
|
&.rotate {
|
||||||
|
transform: rotate(180deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.morphing-dropdown {
|
||||||
|
@include morphing-dropdown();
|
||||||
|
position: absolute;
|
||||||
|
top: calc(100% + 8px);
|
||||||
|
right: 0;
|
||||||
|
min-width: 150px;
|
||||||
|
z-index: $z-dropdown;
|
||||||
|
|
||||||
|
.dropdown-option {
|
||||||
|
padding: 0.5rem 1rem;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all $transition-fast;
|
||||||
|
color: $neutral-700;
|
||||||
|
font-size: $text-sm;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: rgba($blue-500, 0.1);
|
||||||
|
color: $blue-600;
|
||||||
|
padding-left: 1.25rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Neumorphic Elements
|
||||||
|
.neumorphic-card {
|
||||||
|
background: linear-gradient(145deg, #ffffff, #f0f0f0);
|
||||||
|
border-radius: $radius-xl;
|
||||||
|
box-shadow: $shadow-soft-md;
|
||||||
|
}
|
||||||
|
|
||||||
|
.neumorphic-button {
|
||||||
|
@include neumorphic-button();
|
||||||
|
padding: 0.75rem 1.5rem;
|
||||||
|
border: none;
|
||||||
|
border-radius: $radius-lg;
|
||||||
|
font-weight: $font-medium;
|
||||||
|
color: $neutral-700;
|
||||||
|
cursor: pointer;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
|
||||||
|
&.primary {
|
||||||
|
background: linear-gradient(145deg, $primary-600, $primary-700);
|
||||||
|
color: white;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: linear-gradient(145deg, $primary-700, $primary-800);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.small {
|
||||||
|
padding: 0.5rem 0.75rem;
|
||||||
|
font-size: $text-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.full-width {
|
||||||
|
width: 100%;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.neumorphic-inset {
|
||||||
|
box-shadow: $shadow-inset-sm;
|
||||||
|
background: linear-gradient(145deg, #e6e6e6, #ffffff);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transitions
|
||||||
|
.morph-enter-active,
|
||||||
|
.morph-leave-active {
|
||||||
|
transition: all 0.3s $spring-smooth;
|
||||||
|
}
|
||||||
|
|
||||||
|
.morph-enter-from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: scale(0.95) translateY(-10px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.morph-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
transform: scale(0.95) translateY(-10px);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,175 @@
|
||||||
|
<template>
|
||||||
|
<div class="design-test-page">
|
||||||
|
<div class="container">
|
||||||
|
<h1 class="page-title">New Design System Test Pages</h1>
|
||||||
|
<p class="page-subtitle">Testing implementation of the new Neumorphic design with morphing dropdowns</p>
|
||||||
|
|
||||||
|
<div class="navigation-grid">
|
||||||
|
<NuxtLink to="/admin/dashboard-v2" class="nav-card neumorphic-card">
|
||||||
|
<Icon name="mdi:view-dashboard" class="nav-icon" />
|
||||||
|
<h2>Admin Dashboard V2</h2>
|
||||||
|
<p>New admin dashboard with neumorphic design and morphing dropdowns</p>
|
||||||
|
</NuxtLink>
|
||||||
|
|
||||||
|
<NuxtLink to="/board/dashboard-v2" class="nav-card neumorphic-card">
|
||||||
|
<Icon name="mdi:chart-box" class="nav-icon" />
|
||||||
|
<h2>Board Dashboard V2</h2>
|
||||||
|
<p>Executive dashboard with KPIs and strategic insights</p>
|
||||||
|
</NuxtLink>
|
||||||
|
|
||||||
|
<NuxtLink to="/admin/dashboard" class="nav-card neumorphic-card">
|
||||||
|
<Icon name="mdi:view-dashboard-outline" class="nav-icon" />
|
||||||
|
<h2>Current Admin Dashboard</h2>
|
||||||
|
<p>Compare with the existing admin dashboard</p>
|
||||||
|
</NuxtLink>
|
||||||
|
|
||||||
|
<NuxtLink to="/board/dashboard" class="nav-card neumorphic-card">
|
||||||
|
<Icon name="mdi:chart-box-outline" class="nav-icon" />
|
||||||
|
<h2>Current Board Dashboard</h2>
|
||||||
|
<p>Compare with the existing board dashboard</p>
|
||||||
|
</NuxtLink>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="design-info">
|
||||||
|
<h3>Design System Features</h3>
|
||||||
|
<ul>
|
||||||
|
<li>✨ Neumorphic cards and buttons with soft shadows</li>
|
||||||
|
<li>💧 Glassmorphic blue morphing dropdowns</li>
|
||||||
|
<li>🎯 Monaco red primary color maintained</li>
|
||||||
|
<li>📱 Responsive grid layouts</li>
|
||||||
|
<li>🎨 Professional and inviting aesthetic</li>
|
||||||
|
<li>⚡ Smooth spring animations</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
// No authentication required for testing
|
||||||
|
definePageMeta({
|
||||||
|
auth: false,
|
||||||
|
layout: false
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
// Import the new design system
|
||||||
|
@import '@/design-mockups/styles/design-system.scss';
|
||||||
|
|
||||||
|
.design-test-page {
|
||||||
|
min-height: 100vh;
|
||||||
|
background: linear-gradient(135deg, $neutral-50 0%, $neutral-100 100%);
|
||||||
|
padding: 3rem 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
max-width: 1200px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-title {
|
||||||
|
text-align: center;
|
||||||
|
font-size: $text-4xl;
|
||||||
|
font-weight: $font-bold;
|
||||||
|
background: linear-gradient(135deg, $primary-600, $primary-800);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
background-clip: text;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-subtitle {
|
||||||
|
text-align: center;
|
||||||
|
color: $neutral-600;
|
||||||
|
font-size: $text-lg;
|
||||||
|
margin-bottom: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navigation-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||||
|
gap: 2rem;
|
||||||
|
margin-bottom: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-card {
|
||||||
|
@include neumorphic-card('md');
|
||||||
|
padding: 2rem;
|
||||||
|
text-decoration: none;
|
||||||
|
color: inherit;
|
||||||
|
transition: all $transition-base;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
@include neumorphic-card('lg');
|
||||||
|
transform: translateY(-4px);
|
||||||
|
|
||||||
|
.nav-icon {
|
||||||
|
transform: scale(1.1);
|
||||||
|
color: $primary-600;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-icon {
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
color: $neutral-600;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
transition: all $transition-base;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: $text-xl;
|
||||||
|
font-weight: $font-semibold;
|
||||||
|
color: $neutral-800;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: $text-sm;
|
||||||
|
color: $neutral-600;
|
||||||
|
line-height: $leading-relaxed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.design-info {
|
||||||
|
@include neumorphic-card('lg');
|
||||||
|
padding: 2rem;
|
||||||
|
max-width: 600px;
|
||||||
|
margin: 0 auto;
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: $text-xl;
|
||||||
|
font-weight: $font-semibold;
|
||||||
|
color: $neutral-800;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
li {
|
||||||
|
padding: 0.75rem 0;
|
||||||
|
color: $neutral-700;
|
||||||
|
font-size: $text-base;
|
||||||
|
border-bottom: 1px solid rgba($neutral-200, 0.5);
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Neumorphic Elements
|
||||||
|
.neumorphic-card {
|
||||||
|
background: linear-gradient(145deg, #ffffff, #f0f0f0);
|
||||||
|
border-radius: $radius-xl;
|
||||||
|
box-shadow: $shadow-soft-md;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Loading…
Reference in New Issue