From 05b89778cf7da31014522cbaae1d9e431bda671e Mon Sep 17 00:00:00 2001 From: Denis Lugowski Date: Sun, 15 Feb 2026 09:59:15 +0100 Subject: [PATCH] feat: Add new design closer to gremiumhub landing --- .../login/resources/css/styles.css | 169 +++++++++++++----- legalconsenthub/app/app.config.ts | 17 +- legalconsenthub/app/assets/css/main.css | 103 +++++++++-- .../components/FormStepperWithNavigation.vue | 79 ++++---- .../app/composables/useSectionSpawning.ts | 4 +- legalconsenthub/app/layouts/auth.vue | 60 ++++++- legalconsenthub/app/layouts/default.vue | 2 +- .../application-forms/[id]/[sectionIndex].vue | 6 +- legalconsenthub/app/pages/index.vue | 17 +- legalconsenthub/app/pages/login.vue | 4 +- 10 files changed, 358 insertions(+), 103 deletions(-) diff --git a/deployment/keycloak-theme/legalconsenthub/login/resources/css/styles.css b/deployment/keycloak-theme/legalconsenthub/login/resources/css/styles.css index 8edf3dd..746dce1 100644 --- a/deployment/keycloak-theme/legalconsenthub/login/resources/css/styles.css +++ b/deployment/keycloak-theme/legalconsenthub/login/resources/css/styles.css @@ -1,20 +1,46 @@ /* LegalConsentHub Keycloak Theme - Matching Nuxt UI 4 Styling */ /* Compatible with Keycloak 26+ PatternFly-based themes */ -/* CSS Variables matching Nuxt UI green/zinc theme */ +/* CSS Variables matching Nuxt UI teal/cyan/violet theme */ :root { - /* Green palette (primary) */ - --lch-green-50: #effdf5; - --lch-green-100: #d9fbe8; - --lch-green-200: #b3f5d1; - --lch-green-300: #75edae; - --lch-green-400: #00dc82; - --lch-green-500: #00c16a; - --lch-green-600: #00a155; - --lch-green-700: #007f45; - --lch-green-800: #016538; - --lch-green-900: #0a5331; - --lch-green-950: #052e16; + /* Teal palette (primary) */ + --lch-teal-50: #f0fdfa; + --lch-teal-100: #ccfbf1; + --lch-teal-200: #99f6e4; + --lch-teal-300: #5eead4; + --lch-teal-400: #2dd4bf; + --lch-teal-500: #14b8a6; + --lch-teal-600: #0d9488; + --lch-teal-700: #0f766e; + --lch-teal-800: #115e59; + --lch-teal-900: #134e4a; + --lch-teal-950: #042f2e; + + /* Cyan palette (accent) */ + --lch-cyan-50: #ecfeff; + --lch-cyan-100: #cffafe; + --lch-cyan-200: #a5f3fc; + --lch-cyan-300: #67e8f9; + --lch-cyan-400: #22d3ee; + --lch-cyan-500: #06b6d4; + --lch-cyan-600: #0891b2; + --lch-cyan-700: #0e7490; + --lch-cyan-800: #155e75; + --lch-cyan-900: #164e63; + --lch-cyan-950: #083344; + + /* Violet palette (highlight accent) */ + --lch-violet-50: #f5f3ff; + --lch-violet-100: #ede9fe; + --lch-violet-200: #ddd6fe; + --lch-violet-300: #c4b5fd; + --lch-violet-400: #a78bfa; + --lch-violet-500: #8b5cf6; + --lch-violet-600: #7c3aed; + --lch-violet-700: #6d28d9; + --lch-violet-800: #5b21b6; + --lch-violet-900: #4c1d95; + --lch-violet-950: #2e1065; /* Zinc palette (neutral) */ --lch-zinc-50: #fafafa; @@ -40,8 +66,56 @@ html.login-pf body { height: 100%; margin: 0; padding: 0; - background: linear-gradient(135deg, var(--lch-zinc-100) 0%, var(--lch-zinc-200) 100%) !important; + background: linear-gradient(180deg, #ffffff 0%, var(--lch-teal-50) 50%, var(--lch-cyan-50) 100%) !important; font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif !important; + position: relative !important; + overflow: hidden !important; +} + +/* Decorative gradient orbs - matching auth layout */ +html.login-pf::before, +html.login-pf::after { + content: "" !important; + position: fixed !important; + border-radius: 50% !important; + filter: blur(80px) !important; + opacity: 0.4 !important; + pointer-events: none !important; + z-index: 0 !important; +} + +/* Teal/cyan orb - top right */ +html.login-pf::before { + width: 400px !important; + height: 400px !important; + top: -100px !important; + right: -100px !important; + background: linear-gradient(135deg, var(--lch-teal-500), var(--lch-cyan-400)) !important; +} + +/* Cyan/teal orb - bottom left */ +html.login-pf::after { + width: 300px !important; + height: 300px !important; + bottom: -50px !important; + left: -50px !important; + background: linear-gradient(135deg, var(--lch-cyan-400), var(--lch-teal-500)) !important; +} + +/* Violet orb via body pseudo-element - bottom right */ +html.login-pf body::before { + content: "" !important; + position: fixed !important; + width: 200px !important; + height: 200px !important; + bottom: -50px !important; + right: 20% !important; + border-radius: 50% !important; + filter: blur(80px) !important; + opacity: 0.3 !important; + background: linear-gradient(135deg, var(--lch-violet-400), var(--lch-violet-600)) !important; + pointer-events: none !important; + z-index: 0 !important; } .login-pf-page { @@ -52,6 +126,8 @@ html.login-pf body { min-height: 100vh !important; padding: 1rem !important; box-sizing: border-box !important; + position: relative !important; + z-index: 1 !important; } /* Hide the default header with realm name */ @@ -139,8 +215,8 @@ input[type="email"] { input[type="text"]:focus, input[type="password"]:focus, input[type="email"]:focus { - border-color: var(--lch-green-400) !important; - box-shadow: 0 0 0 3px rgba(0, 220, 130, 0.2) !important; + border-color: var(--lch-teal-400) !important; + box-shadow: 0 0 0 3px rgba(20, 184, 166, 0.2) !important; } .pf-c-form-control:hover, @@ -159,28 +235,29 @@ input[type="email"]:hover { font-weight: 500 !important; line-height: 1.5 !important; color: white !important; - background-color: var(--lch-green-500) !important; + background: linear-gradient(135deg, var(--lch-teal-500) 0%, var(--lch-cyan-500) 100%) !important; border: none !important; - border-radius: 0.5rem !important; + border-radius: 0.75rem !important; cursor: pointer !important; - transition: background-color 0.15s ease-in-out, transform 0.1s ease-in-out, box-shadow 0.15s ease-in-out !important; + transition: all 0.2s ease-in-out !important; text-align: center !important; box-sizing: border-box !important; + box-shadow: 0 4px 14px -2px rgba(20, 184, 166, 0.4) !important; } #kc-login:hover { - background-color: var(--lch-green-400) !important; - box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1) !important; + background: linear-gradient(135deg, var(--lch-cyan-500) 0%, var(--lch-violet-500) 100%) !important; + box-shadow: 0 6px 20px -2px rgba(139, 92, 246, 0.4) !important; } #kc-login:active { - background-color: var(--lch-green-700) !important; + background: linear-gradient(135deg, var(--lch-teal-600) 0%, var(--lch-cyan-600) 100%) !important; transform: scale(0.98) !important; } #kc-login:focus { outline: none !important; - box-shadow: 0 0 0 3px rgba(0, 220, 130, 0.3) !important; + box-shadow: 0 0 0 3px rgba(20, 184, 166, 0.3) !important; } /* Secondary/link buttons */ @@ -191,7 +268,7 @@ input[type="email"]:hover { padding: 0.5rem 1rem !important; font-size: 0.875rem !important; font-weight: 500 !important; - color: var(--lch-green-600) !important; + color: var(--lch-teal-600) !important; background-color: transparent !important; border: none !important; cursor: pointer !important; @@ -199,19 +276,19 @@ input[type="email"]:hover { } .pf-c-button.pf-m-link:hover { - color: var(--lch-green-700) !important; + color: var(--lch-teal-700) !important; text-decoration: underline !important; } /* Links */ a { - color: var(--lch-green-600) !important; + color: var(--lch-teal-600) !important; text-decoration: none !important; transition: color 0.15s ease-in-out !important; } a:hover { - color: var(--lch-green-700) !important; + color: var(--lch-teal-700) !important; text-decoration: underline !important; } @@ -241,9 +318,9 @@ a:hover { .alert-success, .pf-m-success { - background-color: var(--lch-green-50) !important; - border: 1px solid var(--lch-green-200) !important; - color: var(--lch-green-700) !important; + background-color: var(--lch-teal-50) !important; + border: 1px solid var(--lch-teal-200) !important; + color: var(--lch-teal-700) !important; } .alert-info, @@ -257,7 +334,7 @@ a:hover { input[type="checkbox"] { width: 1rem !important; height: 1rem !important; - accent-color: var(--lch-green-500) !important; + accent-color: var(--lch-teal-500) !important; border-radius: 0.25rem !important; margin-right: 0.5rem !important; } @@ -372,7 +449,7 @@ input[type="checkbox"] { } .change-username-link:hover { - color: var(--lch-green-600) !important; + color: var(--lch-teal-600) !important; text-decoration: none !important; } @@ -419,7 +496,17 @@ input[readonly]:hover { @media (prefers-color-scheme: dark) { html.login-pf, html.login-pf body { - background: linear-gradient(135deg, var(--lch-zinc-900) 0%, var(--lch-zinc-950) 100%) !important; + background: linear-gradient(180deg, #0a0a0a 0%, var(--lch-teal-950) 50%, var(--lch-cyan-950) 100%) !important; + } + + /* Dark mode orbs - reduced opacity */ + html.login-pf::before, + html.login-pf::after { + opacity: 0.2 !important; + } + + html.login-pf body::before { + opacity: 0.15 !important; } .card-pf { @@ -458,16 +545,16 @@ input[readonly]:hover { input[type="text"]:focus, input[type="password"]:focus, input[type="email"]:focus { - border-color: var(--lch-green-400) !important; - box-shadow: 0 0 0 3px rgba(0, 220, 130, 0.25) !important; + border-color: var(--lch-teal-400) !important; + box-shadow: 0 0 0 3px rgba(20, 184, 166, 0.25) !important; } a { - color: var(--lch-green-400) !important; + color: var(--lch-teal-400) !important; } a:hover { - color: var(--lch-green-300) !important; + color: var(--lch-teal-300) !important; } #kc-form-options label, @@ -496,9 +583,9 @@ input[readonly]:hover { .alert-success, .pf-m-success { - background-color: var(--lch-green-950) !important; - border-color: var(--lch-green-800) !important; - color: var(--lch-green-300) !important; + background-color: var(--lch-teal-950) !important; + border-color: var(--lch-teal-800) !important; + color: var(--lch-teal-300) !important; } .alert-info, @@ -549,7 +636,7 @@ input[readonly]:hover { } .change-username-link:hover { - color: var(--lch-green-400) !important; + color: var(--lch-teal-400) !important; } .input-error { diff --git a/legalconsenthub/app/app.config.ts b/legalconsenthub/app/app.config.ts index aec8967..bc1827f 100644 --- a/legalconsenthub/app/app.config.ts +++ b/legalconsenthub/app/app.config.ts @@ -1,8 +1,23 @@ export default defineAppConfig({ ui: { colors: { - primary: 'green', + primary: 'teal', neutral: 'zinc' + }, + + // Card customizations with vibrant hover effect + card: { + slots: { + root: 'hover:ring-2 hover:ring-teal-400/50 dark:hover:ring-teal-500/40 hover:shadow-lg hover:shadow-teal-500/10 transition-all duration-200' + } + }, + + // Dashboard navbar with glass morphism + dashboardNavbar: { + slots: { + root: 'bg-white/90 dark:bg-gray-950/90 backdrop-blur-xl border-b border-gray-200/50 dark:border-gray-800/50 transition-all duration-300', + title: 'font-semibold text-gray-900 dark:text-white' + } } } }) diff --git a/legalconsenthub/app/assets/css/main.css b/legalconsenthub/app/assets/css/main.css index 759d21f..b18fbeb 100644 --- a/legalconsenthub/app/assets/css/main.css +++ b/legalconsenthub/app/assets/css/main.css @@ -2,15 +2,96 @@ @import '@nuxt/ui'; @theme static { - --color-green-50: #effdf5; - --color-green-100: #d9fbe8; - --color-green-200: #b3f5d1; - --color-green-300: #75edae; - --color-green-400: #00dc82; - --color-green-500: #00c16a; - --color-green-600: #00a155; - --color-green-700: #007f45; - --color-green-800: #016538; - --color-green-900: #0a5331; - --color-green-950: #052e16; + /* Primary color - Teal (matching landing page) */ + --color-teal-50: #f0fdfa; + --color-teal-100: #ccfbf1; + --color-teal-200: #99f6e4; + --color-teal-300: #5eead4; + --color-teal-400: #2dd4bf; + --color-teal-500: #14b8a6; + --color-teal-600: #0d9488; + --color-teal-700: #0f766e; + --color-teal-800: #115e59; + --color-teal-900: #134e4a; + --color-teal-950: #042f2e; + + /* Cyan for accent highlights */ + --color-cyan-50: #ecfeff; + --color-cyan-100: #cffafe; + --color-cyan-200: #a5f3fc; + --color-cyan-300: #67e8f9; + --color-cyan-400: #22d3ee; + --color-cyan-500: #06b6d4; + --color-cyan-600: #0891b2; + --color-cyan-700: #0e7490; + --color-cyan-800: #155e75; + --color-cyan-900: #164e63; + --color-cyan-950: #083344; + + /* Violet color palette (for Tailwind classes and hover effects) */ + --color-violet-50: #f5f3ff; + --color-violet-100: #ede9fe; + --color-violet-200: #ddd6fe; + --color-violet-300: #c4b5fd; + --color-violet-400: #a78bfa; + --color-violet-500: #8b5cf6; + --color-violet-600: #7c3aed; + --color-violet-700: #6d28d9; + --color-violet-800: #5b21b6; + --color-violet-900: #4c1d95; + --color-violet-950: #2e1065; +} + +/* ============================================ + FOCUS & ACCESSIBILITY + ============================================ */ + +/* Global focus styles for elements without built-in focus styling. + Nuxt UI components (inputs, buttons, selects, etc.) have their own + focus ring styling, so we exclude them to avoid double borders. */ +:focus-visible:not(input):not(textarea):not(select):not(button):not([role="combobox"]):not([role="listbox"]):not([role="option"]):not([role="checkbox"]):not([role="radio"]):not([role="switch"]):not([role="slider"]):not([role="tab"]):not([role="menuitem"]) { + outline: 2px solid var(--color-teal-500); + outline-offset: 2px; +} + +/* ============================================ + HEADER STYLING + ============================================ */ + +/* Header logo accent with gradient */ +.header-logo-accent { + background: linear-gradient(135deg, var(--color-teal-500), var(--color-cyan-400)); + box-shadow: 0 4px 6px -1px rgba(20, 184, 166, 0.2); +} + +/* ============================================ + NAVIGATION BUTTON GROUP + ============================================ */ + +.nav-button-group { + display: flex; + gap: 0.75rem; + align-items: center; +} + +@media (max-width: 640px) { + .nav-button-group { + flex-direction: column; + width: 100%; + } + .nav-button-group > * { + width: 100%; + justify-content: center; + } +} + +/* Navigation separator line */ +.nav-separator { + height: 1px; + background: linear-gradient(90deg, transparent, var(--color-gray-200), transparent); + margin-bottom: 1.5rem; +} + +.dark .nav-separator { + background: linear-gradient(90deg, transparent, var(--color-gray-700), transparent); } diff --git a/legalconsenthub/app/components/FormStepperWithNavigation.vue b/legalconsenthub/app/components/FormStepperWithNavigation.vue index 3fe7463..2cd1213 100644 --- a/legalconsenthub/app/components/FormStepperWithNavigation.vue +++ b/legalconsenthub/app/components/FormStepperWithNavigation.vue @@ -99,38 +99,55 @@ -
- - {{ $t('applicationForms.navigation.previous') }} - + +
+ diff --git a/legalconsenthub/app/composables/useSectionSpawning.ts b/legalconsenthub/app/composables/useSectionSpawning.ts index 1d05d59..83ca672 100644 --- a/legalconsenthub/app/composables/useSectionSpawning.ts +++ b/legalconsenthub/app/composables/useSectionSpawning.ts @@ -71,9 +71,7 @@ export function useSectionSpawning() { const newSection = spawnSectionFromTemplate(templateSection, element.reference!, triggerValue) // Find template index - const templateIndex = sections.findIndex( - (s) => s.isTemplate && s.templateReference === trigger.templateReference - ) + const templateIndex = sections.findIndex((s) => s.isTemplate && s.templateReference === trigger.templateReference) if (templateIndex === -1) { // Fallback: append if template not found (shouldn't happen) diff --git a/legalconsenthub/app/layouts/auth.vue b/legalconsenthub/app/layouts/auth.vue index 653ed1b..4f528eb 100644 --- a/legalconsenthub/app/layouts/auth.vue +++ b/legalconsenthub/app/layouts/auth.vue @@ -1,5 +1,61 @@ + + diff --git a/legalconsenthub/app/layouts/default.vue b/legalconsenthub/app/layouts/default.vue index 013122e..aa775f8 100644 --- a/legalconsenthub/app/layouts/default.vue +++ b/legalconsenthub/app/layouts/default.vue @@ -6,7 +6,7 @@ v-model:open="open" collapsible resizable - class="bg-(--ui-bg-elevated)/25" + class="bg-(--ui-bg-elevated)/75 border-r border-(--ui-border)" :ui="{ footer: 'lg:border-t lg:border-(--ui-border)' }" > diff --git a/legalconsenthub/app/pages/index.vue b/legalconsenthub/app/pages/index.vue index d7de478..f9852a2 100644 --- a/legalconsenthub/app/pages/index.vue +++ b/legalconsenthub/app/pages/index.vue @@ -4,6 +4,9 @@ diff --git a/legalconsenthub/app/pages/login.vue b/legalconsenthub/app/pages/login.vue index c02df04..60e1e11 100644 --- a/legalconsenthub/app/pages/login.vue +++ b/legalconsenthub/app/pages/login.vue @@ -3,10 +3,10 @@