22 KiB
22 KiB
MonacoUSA Portal Design System v2.0
Overview
The MonacoUSA Portal design system represents a premium, modern approach to web application interfaces, combining cutting-edge UI patterns with sophisticated animations and interactions. This system prioritizes beauty, functionality, and user engagement through carefully crafted visual experiences.
Design Philosophy
Core Principles
1. Visual Elegance
- Premium aesthetics that reflect Monaco's luxury and sophistication
- Beautiful, engaging interfaces that delight users
- Attention to detail in every interaction
2. Motion & Life
- Smooth, purposeful animations that guide user attention
- Micro-interactions that provide feedback and enhance usability
- Transitions that create seamless navigation experiences
3. Modern Architecture
- Bento grid layouts for flexible content organization
- Component-based design for consistency and maintainability
- Responsive patterns that adapt beautifully across devices
4. Interactive Engagement
- Customizable interfaces that users can personalize
- Draggable and reorderable components
- Real-time updates with smooth animations
🎨 Visual Identity
Brand Colors
Primary Palette
// Monaco Red Spectrum
$monaco-red-50: #fef2f2;
$monaco-red-100: #fee2e2;
$monaco-red-200: #fecaca;
$monaco-red-300: #fca5a5;
$monaco-red-400: #f87171;
$monaco-red-500: #ef4444;
$monaco-red-600: #dc2626; // Primary Brand Color
$monaco-red-700: #b91c1c;
$monaco-red-800: #991b1b;
$monaco-red-900: #7f1d1d;
// Neutral Palette
$gray-50: #fafafa;
$gray-100: #f4f4f5;
$gray-200: #e4e4e7;
$gray-300: #d4d4d8;
$gray-400: #a1a1aa;
$gray-500: #71717a;
$gray-600: #52525b;
$gray-700: #3f3f46;
$gray-800: #27272a;
$gray-900: #18181b;
Gradient Definitions
// Primary Gradients
$gradient-monaco: linear-gradient(135deg, #dc2626 0%, #b91c1c 100%);
$gradient-monaco-light: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
$gradient-monaco-dark: linear-gradient(135deg, #b91c1c 0%, #991b1b 100%);
// Accent Gradients
$gradient-sunset: linear-gradient(135deg, #dc2626 0%, #f59e0b 100%);
$gradient-wine: linear-gradient(135deg, #991b1b 0%, #4c1d95 100%);
$gradient-royal: linear-gradient(135deg, #dc2626 0%, #1e40af 100%);
// Glass Gradients
$gradient-glass-light: linear-gradient(135deg, rgba(255,255,255,0.8) 0%, rgba(255,255,255,0.4) 100%);
$gradient-glass-dark: linear-gradient(135deg, rgba(0,0,0,0.8) 0%, rgba(0,0,0,0.4) 100%);
Typography
Font Stack
// Primary Font Family
$font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
// Monospace Font Family
$font-mono: 'Fira Code', 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', monospace;
// Display Font (for headers)
$font-display: 'Poppins', $font-sans;
Type Scale
// 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
$text-6xl: 3.75rem; // 60px
$text-7xl: 4.5rem; // 72px
// Line Heights
$leading-none: 1;
$leading-tight: 1.25;
$leading-snug: 1.375;
$leading-normal: 1.5;
$leading-relaxed: 1.625;
$leading-loose: 2;
// Font Weights
$font-thin: 100;
$font-light: 300;
$font-normal: 400;
$font-medium: 500;
$font-semibold: 600;
$font-bold: 700;
$font-extrabold: 800;
$font-black: 900;
Spacing System
// Based on 4px grid
$space-0: 0; // 0px
$space-px: 1px; // 1px
$space-0_5: 0.125rem; // 2px
$space-1: 0.25rem; // 4px
$space-1_5: 0.375rem; // 6px
$space-2: 0.5rem; // 8px
$space-2_5: 0.625rem; // 10px
$space-3: 0.75rem; // 12px
$space-3_5: 0.875rem; // 14px
$space-4: 1rem; // 16px
$space-5: 1.25rem; // 20px
$space-6: 1.5rem; // 24px
$space-7: 1.75rem; // 28px
$space-8: 2rem; // 32px
$space-9: 2.25rem; // 36px
$space-10: 2.5rem; // 40px
$space-12: 3rem; // 48px
$space-14: 3.5rem; // 56px
$space-16: 4rem; // 64px
$space-20: 5rem; // 80px
$space-24: 6rem; // 96px
$space-28: 7rem; // 112px
$space-32: 8rem; // 128px
Border Radius
$radius-none: 0;
$radius-sm: 0.125rem; // 2px
$radius-base: 0.25rem; // 4px
$radius-md: 0.375rem; // 6px
$radius-lg: 0.5rem; // 8px
$radius-xl: 0.75rem; // 12px
$radius-2xl: 1rem; // 16px
$radius-3xl: 1.5rem; // 24px
$radius-full: 9999px; // Pill shape
Shadows
// Elevation Shadows
$shadow-xs: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
$shadow-sm: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px -1px rgba(0, 0, 0, 0.1);
$shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1);
$shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1);
$shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1);
$shadow-2xl: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
// Glass Shadows
$shadow-glass: 0 8px 32px rgba(0, 0, 0, 0.1);
$shadow-glass-hover: 0 12px 40px rgba(0, 0, 0, 0.15);
// Monaco Brand Shadows
$shadow-monaco: 0 10px 40px rgba(220, 38, 38, 0.15);
$shadow-monaco-intense: 0 20px 60px rgba(220, 38, 38, 0.25);
🎯 Component Patterns
Glass Morphism
@mixin glass-effect($bg-opacity: 0.7, $blur: 20px) {
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);
box-shadow: $shadow-glass;
}
@mixin glass-dark($bg-opacity: 0.7, $blur: 20px) {
background: rgba(0, 0, 0, $bg-opacity);
backdrop-filter: blur($blur);
-webkit-backdrop-filter: blur($blur);
border: 1px solid rgba(255, 255, 255, 0.1);
box-shadow: $shadow-glass;
}
@mixin glass-colored($color: $monaco-red-600, $opacity: 0.1, $blur: 20px) {
background: rgba($color, $opacity);
backdrop-filter: blur($blur);
-webkit-backdrop-filter: blur($blur);
border: 1px solid rgba($color, 0.2);
box-shadow: 0 8px 32px rgba($color, 0.1);
}
Animation Patterns
// Timing Functions
$ease-in-out-smooth: cubic-bezier(0.4, 0, 0.2, 1);
$ease-out-back: cubic-bezier(0.34, 1.56, 0.64, 1);
$ease-in-out-elastic: cubic-bezier(0.68, -0.55, 0.265, 1.55);
// Duration Scale
$duration-instant: 0ms;
$duration-fast: 150ms;
$duration-base: 300ms;
$duration-slow: 500ms;
$duration-slower: 700ms;
$duration-slowest: 1000ms;
// Animation Mixins
@mixin hover-lift($distance: -2px, $duration: $duration-base) {
transition: transform $duration $ease-in-out-smooth;
&:hover {
transform: translateY($distance);
}
}
@mixin hover-scale($scale: 1.05, $duration: $duration-base) {
transition: transform $duration $ease-in-out-smooth;
&:hover {
transform: scale($scale);
}
}
@mixin pulse-animation($scale: 1.05, $duration: 2s) {
animation: pulse $duration infinite;
@keyframes pulse {
0%, 100% {
transform: scale(1);
opacity: 1;
}
50% {
transform: scale($scale);
opacity: 0.8;
}
}
}
@mixin float-animation($distance: 10px, $duration: 3s) {
animation: float $duration ease-in-out infinite;
@keyframes float {
0%, 100% {
transform: translateY(0);
}
50% {
transform: translateY(-$distance);
}
}
}
Button Variants
// Base Button
@mixin button-base {
display: inline-flex;
align-items: center;
justify-content: center;
padding: $space-2_5 $space-5;
font-weight: $font-medium;
font-size: $text-sm;
line-height: $leading-tight;
border-radius: $radius-xl;
transition: all $duration-base $ease-in-out-smooth;
cursor: pointer;
user-select: none;
&:disabled {
opacity: 0.5;
cursor: not-allowed;
}
}
// Primary Button
@mixin button-primary {
@include button-base;
background: $gradient-monaco;
color: white;
border: none;
box-shadow: $shadow-md;
&:hover:not(:disabled) {
box-shadow: $shadow-monaco;
transform: translateY(-1px);
}
&:active:not(:disabled) {
transform: translateY(0);
}
}
// Glass Button
@mixin button-glass {
@include button-base;
@include glass-effect(0.8, 10px);
color: $monaco-red-600;
&:hover:not(:disabled) {
background: rgba(255, 255, 255, 0.9);
box-shadow: $shadow-glass-hover;
transform: translateY(-1px);
}
}
// Ghost Button
@mixin button-ghost {
@include button-base;
background: transparent;
color: $monaco-red-600;
border: 2px solid $monaco-red-600;
&:hover:not(:disabled) {
background: rgba($monaco-red-600, 0.1);
border-color: $monaco-red-700;
}
}
Card Patterns
// Base Card
@mixin card-base {
border-radius: $radius-2xl;
padding: $space-6;
transition: all $duration-base $ease-in-out-smooth;
}
// Glass Card
@mixin card-glass {
@include card-base;
@include glass-effect;
&:hover {
@include hover-lift(-4px);
box-shadow: $shadow-glass-hover;
}
}
// Gradient Card
@mixin card-gradient {
@include card-base;
background: $gradient-monaco;
color: white;
box-shadow: $shadow-monaco;
&:hover {
@include hover-lift(-4px);
box-shadow: $shadow-monaco-intense;
}
}
// Floating Card
@mixin card-floating {
@include card-base;
background: white;
box-shadow: $shadow-lg;
@include float-animation(5px, 4s);
&:hover {
animation-play-state: paused;
box-shadow: $shadow-xl;
}
}
Form Elements
// Input Base
@mixin input-base {
width: 100%;
padding: $space-3 $space-4;
font-size: $text-base;
border-radius: $radius-xl;
transition: all $duration-base $ease-in-out-smooth;
&:focus {
outline: none;
}
&::placeholder {
color: $gray-400;
}
}
// Glass Input
@mixin input-glass {
@include input-base;
@include glass-effect(0.6, 10px);
border: 2px solid transparent;
&:focus {
border-color: $monaco-red-600;
background: rgba(255, 255, 255, 0.8);
box-shadow: 0 0 0 3px rgba($monaco-red-600, 0.1);
}
}
// Floating Label
@mixin floating-label {
position: relative;
label {
position: absolute;
left: $space-4;
top: 50%;
transform: translateY(-50%);
transition: all $duration-base $ease-in-out-smooth;
pointer-events: none;
color: $gray-500;
font-size: $text-base;
}
input:focus + label,
input:not(:placeholder-shown) + label {
top: 0;
transform: translateY(-50%) scale(0.8);
background: white;
padding: 0 $space-2;
color: $monaco-red-600;
}
}
🎭 Animation Library
Entrance Animations
@keyframes fade-in {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes slide-up {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes scale-in {
from {
opacity: 0;
transform: scale(0.9);
}
to {
opacity: 1;
transform: scale(1);
}
}
@keyframes rotate-in {
from {
opacity: 0;
transform: rotate(-10deg) scale(0.9);
}
to {
opacity: 1;
transform: rotate(0) scale(1);
}
}
Interaction Animations
@keyframes bounce {
0%, 100% {
transform: translateY(0);
}
50% {
transform: translateY(-10px);
}
}
@keyframes shake {
0%, 100% {
transform: translateX(0);
}
25% {
transform: translateX(-5px);
}
75% {
transform: translateX(5px);
}
}
@keyframes wiggle {
0%, 100% {
transform: rotate(0deg);
}
25% {
transform: rotate(-3deg);
}
75% {
transform: rotate(3deg);
}
}
Loading Animations
@keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
@keyframes pulse-ring {
0% {
transform: scale(0.5);
opacity: 1;
}
80%, 100% {
transform: scale(1.5);
opacity: 0;
}
}
@keyframes shimmer {
0% {
background-position: -200% 0;
}
100% {
background-position: 200% 0;
}
}
.shimmer-effect {
background: linear-gradient(
90deg,
rgba(255, 255, 255, 0) 0%,
rgba(255, 255, 255, 0.3) 50%,
rgba(255, 255, 255, 0) 100%
);
background-size: 200% 100%;
animation: shimmer 1.5s infinite;
}
📱 Responsive Design
Breakpoints
// Mobile First Breakpoints
$screen-sm: 640px; // Small devices
$screen-md: 768px; // Medium devices
$screen-lg: 1024px; // Large devices
$screen-xl: 1280px; // Extra large devices
$screen-2xl: 1536px; // 2X Extra large devices
// Mixins
@mixin sm {
@media (min-width: $screen-sm) {
@content;
}
}
@mixin md {
@media (min-width: $screen-md) {
@content;
}
}
@mixin lg {
@media (min-width: $screen-lg) {
@content;
}
}
@mixin xl {
@media (min-width: $screen-xl) {
@content;
}
}
@mixin 2xl {
@media (min-width: $screen-2xl) {
@content;
}
}
Container Widths
.container {
width: 100%;
margin-left: auto;
margin-right: auto;
padding-left: $space-4;
padding-right: $space-4;
@include sm {
max-width: $screen-sm;
}
@include md {
max-width: $screen-md;
}
@include lg {
max-width: $screen-lg;
}
@include xl {
max-width: $screen-xl;
}
@include 2xl {
max-width: $screen-2xl;
}
}
🎪 Motion Preferences
// Respect user's motion preferences
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
}
// Dark mode support
@media (prefers-color-scheme: dark) {
:root {
--bg-primary: #{$gray-900};
--text-primary: #{$gray-50};
--glass-bg: rgba(0, 0, 0, 0.7);
--glass-border: rgba(255, 255, 255, 0.1);
}
}
🔧 Utility Classes
Display Utilities
.hidden { display: none; }
.block { display: block; }
.inline-block { display: inline-block; }
.inline { display: inline; }
.flex { display: flex; }
.inline-flex { display: inline-flex; }
.grid { display: grid; }
// Flexbox Utilities
.items-start { align-items: flex-start; }
.items-center { align-items: center; }
.items-end { align-items: flex-end; }
.justify-start { justify-content: flex-start; }
.justify-center { justify-content: center; }
.justify-end { justify-content: flex-end; }
.justify-between { justify-content: space-between; }
.flex-row { flex-direction: row; }
.flex-col { flex-direction: column; }
.flex-wrap { flex-wrap: wrap; }
.flex-1 { flex: 1 1 0%; }
.flex-auto { flex: 1 1 auto; }
Spacing Utilities
// Margin
@each $name, $size in (
'0': $space-0,
'1': $space-1,
'2': $space-2,
'3': $space-3,
'4': $space-4,
'5': $space-5,
'6': $space-6,
'8': $space-8,
'10': $space-10,
'12': $space-12,
'16': $space-16
) {
.m-#{$name} { margin: $size; }
.mt-#{$name} { margin-top: $size; }
.mr-#{$name} { margin-right: $size; }
.mb-#{$name} { margin-bottom: $size; }
.ml-#{$name} { margin-left: $size; }
.mx-#{$name} {
margin-left: $size;
margin-right: $size;
}
.my-#{$name} {
margin-top: $size;
margin-bottom: $size;
}
}
// Padding (same pattern as margin)
Text Utilities
// Font Size
.text-xs { font-size: $text-xs; }
.text-sm { font-size: $text-sm; }
.text-base { font-size: $text-base; }
.text-lg { font-size: $text-lg; }
.text-xl { font-size: $text-xl; }
.text-2xl { font-size: $text-2xl; }
.text-3xl { font-size: $text-3xl; }
.text-4xl { font-size: $text-4xl; }
// Font Weight
.font-thin { font-weight: $font-thin; }
.font-light { font-weight: $font-light; }
.font-normal { font-weight: $font-normal; }
.font-medium { font-weight: $font-medium; }
.font-semibold { font-weight: $font-semibold; }
.font-bold { font-weight: $font-bold; }
// Text Alignment
.text-left { text-align: left; }
.text-center { text-align: center; }
.text-right { text-align: right; }
.text-justify { text-align: justify; }
🎯 Dashboard Patterns
Bento Grid Layout
Modern dashboard layout using CSS Grid with flexible item placement:
.bento-grid {
display: grid;
grid-template-columns: repeat(12, 1fr);
gap: 1.5rem;
.bento-item {
@include glass-premium;
border-radius: $radius-2xl;
padding: $space-6;
transition: all $duration-base $ease-in-out-smooth;
&--small { grid-column: span 3; }
&--medium { grid-column: span 4; }
&--large { grid-column: span 6; }
&--xlarge { grid-column: span 8; }
&--full { grid-column: span 12; }
&--tall { grid-row: span 2; }
&:hover {
transform: translateY(-4px);
box-shadow: $shadow-glass-hover;
}
}
}
Widget Components
Statistics Card
.stat-card {
@include glass-premium(0.8, 25px);
position: relative;
overflow: hidden;
.stat-value {
font-size: $text-4xl;
font-weight: $font-bold;
background: $gradient-monaco;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.stat-change {
display: inline-flex;
align-items: center;
padding: $space-1 $space-2;
border-radius: $radius-full;
font-size: $text-sm;
font-weight: $font-semibold;
&--positive {
background: rgba($success-500, 0.1);
color: $success-600;
}
&--negative {
background: rgba($monaco-red-500, 0.1);
color: $monaco-red-600;
}
}
.stat-chart {
position: absolute;
bottom: 0;
right: 0;
opacity: 0.2;
}
}
Activity Timeline
.timeline {
position: relative;
&::before {
content: '';
position: absolute;
left: 20px;
top: 0;
bottom: 0;
width: 2px;
background: $gradient-monaco;
opacity: 0.2;
}
.timeline-item {
position: relative;
padding-left: 50px;
margin-bottom: $space-6;
animation: slide-up $duration-base $ease-in-out-smooth;
animation-fill-mode: both;
@for $i from 1 through 10 {
&:nth-child(#{$i}) {
animation-delay: #{$i * 50}ms;
}
}
.timeline-marker {
position: absolute;
left: 10px;
top: 0;
width: 20px;
height: 20px;
border-radius: $radius-full;
background: white;
border: 3px solid $monaco-red-600;
z-index: 1;
&.pulse {
&::after {
content: '';
position: absolute;
inset: -5px;
border-radius: $radius-full;
border: 2px solid $monaco-red-600;
animation: pulse-ring 2s infinite;
}
}
}
}
}
Draggable Dashboard
.draggable-grid {
.drag-handle {
position: absolute;
top: $space-4;
right: $space-4;
cursor: grab;
opacity: 0;
transition: opacity $duration-base;
&:active {
cursor: grabbing;
}
}
.draggable-item {
&:hover .drag-handle {
opacity: 0.5;
}
&.dragging {
opacity: 0.5;
transform: scale(1.05);
z-index: 1000;
}
&.drag-over {
background: rgba($monaco-red-600, 0.05);
border: 2px dashed $monaco-red-600;
}
}
}
Enhanced Glass Effects
@mixin glass-premium($opacity: 0.7, $blur: 30px) {
background: linear-gradient(135deg,
rgba(255, 255, 255, $opacity),
rgba(255, 255, 255, $opacity * 0.6)
);
backdrop-filter: blur($blur) saturate(180%);
-webkit-backdrop-filter: blur($blur) saturate(180%);
border: 1px solid rgba(255, 255, 255, 0.3);
box-shadow:
0 8px 32px rgba(0, 0, 0, 0.1),
inset 0 1px 0 rgba(255, 255, 255, 0.5),
inset 0 -1px 0 rgba(0, 0, 0, 0.1);
}
@mixin glass-frosted($color: white, $opacity: 0.1) {
background: rgba($color, $opacity);
backdrop-filter: blur(40px) saturate(200%) contrast(120%);
-webkit-backdrop-filter: blur(40px) saturate(200%) contrast(120%);
border: 1px solid rgba($color, 0.2);
box-shadow:
0 20px 40px rgba(0, 0, 0, 0.1),
inset 0 0 0 1px rgba(255, 255, 255, 0.1);
}
Animation Patterns for Dashboard
Number Counter Animation
@keyframes count-up {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.counter {
display: inline-block;
animation: count-up $duration-slow $ease-out-back;
.digit {
display: inline-block;
animation: count-up $duration-slow $ease-out-back;
animation-fill-mode: both;
@for $i from 1 through 10 {
&:nth-child(#{$i}) {
animation-delay: #{$i * 50}ms;
}
}
}
}
Progress Ring
.progress-ring {
position: relative;
width: 120px;
height: 120px;
svg {
transform: rotate(-90deg);
}
.progress-ring-circle {
fill: none;
stroke-width: 8;
&--bg {
stroke: rgba($gray-300, 0.3);
}
&--fill {
stroke: url(#gradient-monaco);
stroke-linecap: round;
transition: stroke-dashoffset $duration-slow $ease-in-out-smooth;
}
}
.progress-value {
position: absolute;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
font-size: $text-2xl;
font-weight: $font-bold;
}
}
VueUse Motion Integration
Configuration
// Motion variants for dashboard components
export const dashboardMotions = {
// Card entrance
cardEnter: {
initial: { opacity: 0, scale: 0.9 },
enter: {
opacity: 1,
scale: 1,
transition: {
type: 'spring',
stiffness: 200,
damping: 20
}
}
},
// Statistics counter
statCounter: {
initial: { opacity: 0, y: 20 },
visible: {
opacity: 1,
y: 0,
transition: {
duration: 600,
ease: 'easeOut'
}
}
},
// Timeline item
timelineItem: {
initial: { opacity: 0, x: -20 },
visibleOnce: {
opacity: 1,
x: 0,
transition: {
duration: 500,
delay: 100
}
}
},
// Hover lift
hoverLift: {
initial: { scale: 1 },
hovered: {
scale: 1.02,
y: -4,
transition: {
type: 'spring',
stiffness: 400,
damping: 10
}
}
}
}
Usage Example
<template>
<div class="bento-grid">
<div
v-motion="'statsCard'"
:initial="{ opacity: 0, y: 20 }"
:enter="{
opacity: 1,
y: 0,
transition: {
delay: index * 100,
duration: 500
}
}"
:hovered="{
scale: 1.02,
y: -4
}"
class="bento-item bento-item--medium stat-card"
>
<!-- Card content -->
</div>
</div>
</template>
MonacoUSA Portal Design System v2.0 - Premium Design for Premium Experiences