From a0d703e7cb7cf324cc9b00b55bc5da9f63de63d5 Mon Sep 17 00:00:00 2001 From: Matt Date: Sat, 6 Sep 2025 15:17:54 +0200 Subject: [PATCH] Implement bright glassmorphic UI redesign for Board dashboard MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add Tailwind CSS configuration with bright glass utilities - Create glass components (Sidebar, StatCard, DuesCard) with Lucide icons - Implement new dashboard with limited dues display (4 cards max vs 30+) - Use translucent white glass effects with Monaco red accents - Improve visual hierarchy and reduce UI clutter 🤖 Generated with Claude Code Co-Authored-By: Claude --- assets/css/tailwind.css | 291 ++++++++++++++++++ components/CountUp.vue | 70 +++++ components/GlassDuesCard.vue | 229 ++++++++++++++ components/GlassSidebar.vue | 277 +++++++++++++++++ components/GlassStatCard.vue | 192 ++++++++++++ components/SidebarLink.vue | 111 +++++++ nuxt.config.ts | 8 +- pages/board/dashboard/index-glass.vue | 425 ++++++++++++++++++++++++++ postcss.config.js | 6 + tailwind.config.js | 249 +++++++++++++++ 10 files changed, 1857 insertions(+), 1 deletion(-) create mode 100644 assets/css/tailwind.css create mode 100644 components/CountUp.vue create mode 100644 components/GlassDuesCard.vue create mode 100644 components/GlassSidebar.vue create mode 100644 components/GlassStatCard.vue create mode 100644 components/SidebarLink.vue create mode 100644 pages/board/dashboard/index-glass.vue create mode 100644 postcss.config.js create mode 100644 tailwind.config.js diff --git a/assets/css/tailwind.css b/assets/css/tailwind.css new file mode 100644 index 0000000..6eb8b39 --- /dev/null +++ b/assets/css/tailwind.css @@ -0,0 +1,291 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +/* Base layer overrides */ +@layer base { + html { + @apply scroll-smooth; + } + + body { + @apply bg-gradient-light min-h-screen antialiased; + font-family: 'Inter', system-ui, -apple-system, sans-serif; + } + + /* Typography defaults */ + h1 { + @apply text-4xl font-bold text-gray-800; + } + + h2 { + @apply text-3xl font-bold text-gray-800; + } + + h3 { + @apply text-2xl font-semibold text-gray-700; + } + + h4 { + @apply text-xl font-semibold text-gray-700; + } + + p { + @apply text-gray-600; + } +} + +/* Component layer */ +@layer components { + /* Bright Glass Card Variants */ + .glass-card-bright { + @apply glass rounded-glass p-6 transition-all duration-300; + } + + .glass-card-ultra { + @apply glass-ultra rounded-glass p-6 transition-all duration-300; + } + + .glass-card-monaco { + @apply glass-monaco rounded-glass p-6 transition-all duration-300; + } + + /* Glass Stat Card */ + .glass-stat-card { + @apply glass-light rounded-glass p-6 hover:glass-ultra transition-all duration-300 hover:-translate-y-1 hover:shadow-glass-lg; + } + + .glass-stat-icon { + @apply w-12 h-12 rounded-xl bg-glass-monaco-soft flex items-center justify-center mb-4; + } + + .glass-stat-value { + @apply text-3xl font-bold text-gray-800 mb-1; + } + + .glass-stat-label { + @apply text-sm text-gray-600 uppercase tracking-wide; + } + + /* Glass Dues Card */ + .glass-dues-card { + @apply glass rounded-glass p-4 hover:shadow-glass-lg transition-all duration-300; + } + + .glass-dues-header { + @apply flex items-center justify-between mb-3; + } + + .glass-dues-avatar { + @apply w-10 h-10 rounded-full ring-2 ring-white/60; + } + + .glass-dues-name { + @apply font-semibold text-gray-800; + } + + .glass-dues-amount { + @apply text-lg font-bold text-monaco-600; + } + + .glass-dues-status { + @apply px-3 py-1 rounded-full text-xs font-medium; + } + + .glass-dues-status-overdue { + @apply bg-red-100 text-red-700; + } + + .glass-dues-status-upcoming { + @apply bg-amber-100 text-amber-700; + } + + /* Glass Button Variants */ + .btn-glass { + @apply glass-button px-6 py-2.5 rounded-xl font-medium text-gray-700 hover:text-monaco-600; + } + + .btn-glass-primary { + @apply bg-gradient-monaco text-white px-6 py-2.5 rounded-xl font-medium shadow-monaco-sm hover:shadow-monaco transition-all duration-300 hover:-translate-y-0.5; + } + + .btn-glass-secondary { + @apply glass px-6 py-2.5 rounded-xl font-medium text-monaco-600 border-monaco-200 hover:bg-glass-monaco-soft; + } + + .btn-glass-ghost { + @apply bg-transparent border-2 border-monaco-600 text-monaco-600 px-6 py-2.5 rounded-xl font-medium hover:bg-glass-monaco-soft transition-all duration-300; + } + + /* Glass Navigation Items */ + .nav-item-glass { + @apply flex items-center gap-3 px-4 py-3 rounded-xl transition-all duration-200 text-gray-700 hover:bg-glass-monaco-soft hover:text-monaco-600 hover:translate-x-0.5; + } + + .nav-item-glass-active { + @apply flex items-center gap-3 px-4 py-3 rounded-xl bg-glass-monaco text-monaco-600 font-medium relative; + } + + .nav-item-indicator { + @apply absolute left-0 top-1/2 -translate-y-1/2 w-1 h-8 bg-gradient-monaco rounded-r-full; + } + + /* Glass Input Fields */ + .input-glass { + @apply glass-input px-4 py-3 rounded-xl w-full; + } + + .select-glass { + @apply glass-input px-4 py-3 rounded-xl w-full appearance-none cursor-pointer; + } + + .textarea-glass { + @apply glass-input px-4 py-3 rounded-xl w-full resize-none; + } + + /* Glass Table */ + .table-glass { + @apply glass-ultra rounded-glass overflow-hidden; + } + + .table-glass thead { + @apply bg-glass-monaco-soft border-b border-white/40; + } + + .table-glass th { + @apply px-6 py-4 text-left text-sm font-semibold text-gray-700 uppercase tracking-wider; + } + + .table-glass td { + @apply px-6 py-4 text-gray-600; + } + + .table-glass tbody tr { + @apply border-b border-white/20 hover:bg-glass-monaco-soft transition-colors duration-150; + } + + /* Glass Modal/Dialog */ + .modal-glass { + @apply glass-ultra rounded-glass shadow-2xl; + } + + .modal-glass-header { + @apply px-6 py-4 border-b border-white/40 bg-gradient-glass; + } + + .modal-glass-body { + @apply px-6 py-4; + } + + .modal-glass-footer { + @apply px-6 py-4 border-t border-white/40 bg-glass-monaco-soft flex justify-end gap-3; + } + + /* Glass Badge */ + .badge-glass { + @apply inline-flex items-center px-3 py-1 rounded-full text-xs font-medium bg-glass border border-white/60; + } + + .badge-glass-monaco { + @apply inline-flex items-center px-3 py-1 rounded-full text-xs font-medium bg-glass-monaco text-monaco-700 border-monaco-200; + } + + /* Glass Alert */ + .alert-glass { + @apply glass-light rounded-glass p-4 border-l-4; + } + + .alert-glass-success { + @apply alert-glass border-green-500 text-green-800; + } + + .alert-glass-warning { + @apply alert-glass border-amber-500 text-amber-800; + } + + .alert-glass-error { + @apply alert-glass border-red-500 text-red-800; + } + + .alert-glass-info { + @apply alert-glass border-blue-500 text-blue-800; + } +} + +/* Utility layer */ +@layer utilities { + /* Text gradient utilities */ + .text-gradient-monaco { + @apply bg-gradient-monaco bg-clip-text text-transparent; + } + + /* Hover lift effect */ + .hover-lift { + @apply transition-transform duration-300 hover:-translate-y-1; + } + + /* Hover scale effect */ + .hover-scale { + @apply transition-transform duration-300 hover:scale-105; + } + + /* Focus ring Monaco */ + .focus-monaco { + @apply focus:ring-2 focus:ring-monaco-400 focus:ring-offset-2 focus:outline-none; + } + + /* Loading skeleton */ + .skeleton { + @apply animate-pulse bg-gradient-to-r from-gray-200 via-gray-300 to-gray-200 rounded-lg; + } +} + +/* Custom animations */ +@keyframes float { + 0%, 100% { + transform: translateY(0); + } + 50% { + transform: translateY(-10px); + } +} + +@keyframes shimmer { + 0% { + background-position: -1000px 0; + } + 100% { + background-position: 1000px 0; + } +} + +/* Glass morphism scrollbar */ +::-webkit-scrollbar { + width: 10px; + height: 10px; +} + +::-webkit-scrollbar-track { + background: rgba(0, 0, 0, 0.05); + border-radius: 9999px; +} + +::-webkit-scrollbar-thumb { + background: linear-gradient(135deg, #dc2626 0%, #b91c1c 100%); + border-radius: 9999px; +} + +::-webkit-scrollbar-thumb:hover { + background: linear-gradient(135deg, #b91c1c 0%, #991b1b 100%); +} + +/* Reduced motion preferences */ +@media (prefers-reduced-motion: reduce) { + *, + *::before, + *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + } +} \ No newline at end of file diff --git a/components/CountUp.vue b/components/CountUp.vue new file mode 100644 index 0000000..2bce59f --- /dev/null +++ b/components/CountUp.vue @@ -0,0 +1,70 @@ + + + \ No newline at end of file diff --git a/components/GlassDuesCard.vue b/components/GlassDuesCard.vue new file mode 100644 index 0000000..f5de7ea --- /dev/null +++ b/components/GlassDuesCard.vue @@ -0,0 +1,229 @@ + + + + + \ No newline at end of file diff --git a/components/GlassSidebar.vue b/components/GlassSidebar.vue new file mode 100644 index 0000000..340b5c8 --- /dev/null +++ b/components/GlassSidebar.vue @@ -0,0 +1,277 @@ + + + + + \ No newline at end of file diff --git a/components/GlassStatCard.vue b/components/GlassStatCard.vue new file mode 100644 index 0000000..91a85b3 --- /dev/null +++ b/components/GlassStatCard.vue @@ -0,0 +1,192 @@ + + + \ No newline at end of file diff --git a/components/SidebarLink.vue b/components/SidebarLink.vue new file mode 100644 index 0000000..3e35745 --- /dev/null +++ b/components/SidebarLink.vue @@ -0,0 +1,111 @@ + + + + + \ No newline at end of file diff --git a/nuxt.config.ts b/nuxt.config.ts index 4285951..3daa790 100644 --- a/nuxt.config.ts +++ b/nuxt.config.ts @@ -15,7 +15,13 @@ export default defineNuxtConfig({ } }, modules: ["vuetify-nuxt-module", "@vueuse/motion/nuxt"], - css: ["~/assets/scss/main.scss"], + css: ["~/assets/css/tailwind.css", "~/assets/scss/main.scss"], + postcss: { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, + }, app: { head: { titleTemplate: "%s • MonacoUSA Portal", diff --git a/pages/board/dashboard/index-glass.vue b/pages/board/dashboard/index-glass.vue new file mode 100644 index 0000000..dd85e42 --- /dev/null +++ b/pages/board/dashboard/index-glass.vue @@ -0,0 +1,425 @@ + + + + + \ No newline at end of file diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 0000000..e99ebc2 --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +} \ No newline at end of file diff --git a/tailwind.config.js b/tailwind.config.js new file mode 100644 index 0000000..a50504b --- /dev/null +++ b/tailwind.config.js @@ -0,0 +1,249 @@ +/** @type {import('tailwindcss').Config} */ +export default { + content: [ + "./components/**/*.{js,vue,ts}", + "./layouts/**/*.vue", + "./pages/**/*.vue", + "./plugins/**/*.{js,ts}", + "./app.vue", + "./error.vue", + ], + theme: { + extend: { + colors: { + // Monaco Red Spectrum + 'monaco': { + 50: '#fef2f2', + 100: '#fee2e2', + 200: '#fecaca', + 300: '#fca5a5', + 400: '#f87171', + 500: '#ef4444', + 600: '#dc2626', // Primary + 700: '#b91c1c', + 800: '#991b1b', + 900: '#7f1d1d', + }, + // Glass Colors + 'glass': { + 'white': 'rgba(255, 255, 255, 0.7)', + 'light': 'rgba(255, 255, 255, 0.85)', + 'ultra-light': 'rgba(255, 255, 255, 0.95)', + 'border': 'rgba(255, 255, 255, 0.6)', + 'monaco': 'rgba(220, 38, 38, 0.1)', + 'monaco-soft': 'rgba(220, 38, 38, 0.05)', + }, + }, + backgroundImage: { + // Bright gradients + 'gradient-light': 'linear-gradient(135deg, #f5f5f5 0%, #ffffff 100%)', + 'gradient-soft': 'linear-gradient(135deg, #fafafa 0%, #f5f5f5 100%)', + 'gradient-monaco-soft': 'linear-gradient(135deg, #fff5f5 0%, #ffffff 100%)', + // Monaco gradients + 'gradient-monaco': 'linear-gradient(135deg, #dc2626 0%, #b91c1c 100%)', + 'gradient-monaco-light': 'linear-gradient(135deg, #ef4444 0%, #dc2626 100%)', + // Glass gradients + 'gradient-glass': 'linear-gradient(135deg, rgba(255,255,255,0.9) 0%, rgba(255,255,255,0.6) 100%)', + 'gradient-glass-soft': 'linear-gradient(135deg, rgba(255,255,255,0.7) 0%, rgba(255,255,255,0.4) 100%)', + }, + backdropBlur: { + xs: '2px', + sm: '4px', + md: '8px', + lg: '12px', + xl: '16px', + '2xl': '20px', + '3xl': '30px', + }, + boxShadow: { + 'glass': '0 8px 32px rgba(31, 38, 135, 0.15)', + 'glass-sm': '0 4px 16px rgba(31, 38, 135, 0.1)', + 'glass-lg': '0 12px 48px rgba(31, 38, 135, 0.2)', + 'glass-inset': 'inset 0 2px 4px rgba(255, 255, 255, 0.6), inset 0 -2px 4px rgba(0, 0, 0, 0.05)', + 'monaco': '0 10px 40px rgba(220, 38, 38, 0.15)', + 'monaco-sm': '0 4px 20px rgba(220, 38, 38, 0.1)', + 'monaco-lg': '0 20px 60px rgba(220, 38, 38, 0.2)', + 'soft': '0 2px 8px rgba(0, 0, 0, 0.08)', + 'soft-lg': '0 4px 16px rgba(0, 0, 0, 0.12)', + }, + animation: { + 'fade-in': 'fadeIn 0.3s ease-in-out', + 'slide-up': 'slideUp 0.3s cubic-bezier(0.34, 1.56, 0.64, 1)', + 'slide-down': 'slideDown 0.3s ease-out', + 'scale-in': 'scaleIn 0.3s ease-out', + 'float': 'float 3s ease-in-out infinite', + 'shimmer': 'shimmer 2s infinite', + 'pulse-soft': 'pulseSoft 2s ease-in-out infinite', + 'glow': 'glow 2s ease-in-out infinite', + }, + keyframes: { + fadeIn: { + '0%': { opacity: '0' }, + '100%': { opacity: '1' }, + }, + slideUp: { + '0%': { opacity: '0', transform: 'translateY(20px)' }, + '100%': { opacity: '1', transform: 'translateY(0)' }, + }, + slideDown: { + '0%': { opacity: '0', transform: 'translateY(-20px)' }, + '100%': { opacity: '1', transform: 'translateY(0)' }, + }, + scaleIn: { + '0%': { opacity: '0', transform: 'scale(0.9)' }, + '100%': { opacity: '1', transform: 'scale(1)' }, + }, + float: { + '0%, 100%': { transform: 'translateY(0)' }, + '50%': { transform: 'translateY(-10px)' }, + }, + shimmer: { + '0%': { backgroundPosition: '-1000px 0' }, + '100%': { backgroundPosition: '1000px 0' }, + }, + pulseSoft: { + '0%, 100%': { opacity: '1' }, + '50%': { opacity: '0.8' }, + }, + glow: { + '0%, 100%': { boxShadow: '0 0 20px rgba(220, 38, 38, 0.3)' }, + '50%': { boxShadow: '0 0 30px rgba(220, 38, 38, 0.5)' }, + }, + }, + fontFamily: { + 'sans': ['Inter', 'system-ui', '-apple-system', 'sans-serif'], + }, + borderRadius: { + 'glass': '20px', + }, + transitionTimingFunction: { + 'smooth': 'cubic-bezier(0.4, 0, 0.2, 1)', + 'bounce': 'cubic-bezier(0.34, 1.56, 0.64, 1)', + }, + }, + }, + plugins: [ + // Custom glass utilities plugin + function({ addUtilities, addComponents, theme }) { + // Glass effect utilities + addUtilities({ + '.glass': { + background: 'rgba(255, 255, 255, 0.7)', + backdropFilter: 'blur(20px)', + '-webkit-backdrop-filter': 'blur(20px)', + border: '1px solid rgba(255, 255, 255, 0.6)', + boxShadow: '0 8px 32px rgba(31, 38, 135, 0.15)', + }, + '.glass-light': { + background: 'rgba(255, 255, 255, 0.85)', + backdropFilter: 'blur(20px)', + '-webkit-backdrop-filter': 'blur(20px)', + border: '1px solid rgba(255, 255, 255, 0.7)', + boxShadow: '0 8px 32px rgba(31, 38, 135, 0.12)', + }, + '.glass-ultra': { + background: 'rgba(255, 255, 255, 0.95)', + backdropFilter: 'blur(30px)', + '-webkit-backdrop-filter': 'blur(30px)', + border: '1px solid rgba(255, 255, 255, 0.8)', + boxShadow: '0 8px 32px rgba(31, 38, 135, 0.1), inset 0 2px 4px rgba(255, 255, 255, 0.6)', + }, + '.glass-monaco': { + background: 'linear-gradient(135deg, rgba(220, 38, 38, 0.05) 0%, rgba(255, 255, 255, 0.7) 100%)', + backdropFilter: 'blur(20px)', + '-webkit-backdrop-filter': 'blur(20px)', + borderLeft: '3px solid #dc2626', + border: '1px solid rgba(220, 38, 38, 0.2)', + boxShadow: '0 8px 32px rgba(220, 38, 38, 0.1)', + }, + '.no-scrollbar': { + '-ms-overflow-style': 'none', + 'scrollbar-width': 'none', + '&::-webkit-scrollbar': { + display: 'none', + }, + }, + '.scrollbar-thin': { + 'scrollbar-width': 'thin', + '&::-webkit-scrollbar': { + width: '8px', + height: '8px', + }, + '&::-webkit-scrollbar-track': { + background: 'rgba(0, 0, 0, 0.05)', + borderRadius: '9999px', + }, + '&::-webkit-scrollbar-thumb': { + background: 'linear-gradient(135deg, #dc2626 0%, #b91c1c 100%)', + borderRadius: '9999px', + }, + }, + }); + + // Glass component classes + addComponents({ + '.glass-card': { + background: 'rgba(255, 255, 255, 0.7)', + backdropFilter: 'blur(20px)', + '-webkit-backdrop-filter': 'blur(20px)', + border: '1px solid rgba(255, 255, 255, 0.6)', + boxShadow: '0 8px 32px rgba(31, 38, 135, 0.15)', + borderRadius: '20px', + transition: 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)', + '&:hover': { + background: 'rgba(255, 255, 255, 0.8)', + boxShadow: '0 12px 40px rgba(31, 38, 135, 0.2)', + transform: 'translateY(-4px)', + }, + }, + '.glass-button': { + background: 'rgba(255, 255, 255, 0.7)', + backdropFilter: 'blur(10px)', + '-webkit-backdrop-filter': 'blur(10px)', + border: '1px solid rgba(255, 255, 255, 0.8)', + boxShadow: '0 4px 15px rgba(0, 0, 0, 0.08)', + transition: 'all 0.3s ease', + '&:hover': { + background: 'rgba(255, 255, 255, 0.9)', + boxShadow: '0 6px 20px rgba(220, 38, 38, 0.15)', + transform: 'translateY(-2px)', + }, + '&:active': { + transform: 'translateY(0)', + }, + }, + '.glass-input': { + background: 'rgba(255, 255, 255, 0.7)', + backdropFilter: 'blur(10px)', + '-webkit-backdrop-filter': 'blur(10px)', + border: '1px solid rgba(255, 255, 255, 0.6)', + transition: 'all 0.3s ease', + '&:hover': { + background: 'rgba(255, 255, 255, 0.8)', + borderColor: 'rgba(220, 38, 38, 0.2)', + }, + '&:focus': { + background: 'rgba(255, 255, 255, 0.9)', + borderColor: '#dc2626', + boxShadow: '0 0 0 3px rgba(220, 38, 38, 0.1)', + outline: 'none', + }, + }, + '.glass-sidebar': { + background: 'rgba(255, 255, 255, 0.85)', + backdropFilter: 'blur(30px)', + '-webkit-backdrop-filter': 'blur(30px)', + borderRight: '1px solid rgba(255, 255, 255, 0.6)', + boxShadow: '4px 0 24px rgba(0, 0, 0, 0.08)', + }, + '.glass-navbar': { + background: 'rgba(255, 255, 255, 0.9)', + backdropFilter: 'blur(20px)', + '-webkit-backdrop-filter': 'blur(20px)', + borderBottom: '1px solid rgba(255, 255, 255, 0.6)', + boxShadow: '0 4px 24px rgba(0, 0, 0, 0.08)', + }, + }); + }, + ], +} \ No newline at end of file