From 98ccee866de5796f1867572cf816adc1845effa5 Mon Sep 17 00:00:00 2001 From: Flaminel Date: Thu, 25 Sep 2025 12:06:46 +0300 Subject: [PATCH] Fix sidebar styling (#313) --- .../main-layout/main-layout.component.html | 31 +- .../main-layout/main-layout.component.scss | 705 +----------------- .../main-layout/main-layout.component.ts | 19 +- .../sidebar-content.component.html | 25 +- .../sidebar-content.component.scss | 363 ++++++++- .../sidebar-content.component.ts | 73 +- code/frontend/src/styles.scss | 168 ++--- 7 files changed, 471 insertions(+), 913 deletions(-) diff --git a/code/frontend/src/app/layout/main-layout/main-layout.component.html b/code/frontend/src/app/layout/main-layout/main-layout.component.html index be54ea78..ffd2f13c 100644 --- a/code/frontend/src/app/layout/main-layout/main-layout.component.html +++ b/code/frontend/src/app/layout/main-layout/main-layout.component.html @@ -6,13 +6,11 @@
- @@ -24,7 +22,7 @@
+ (click)="sidebarContent.toggleMobileDrawer()">
- - -
- - - - - -
-
-
diff --git a/code/frontend/src/app/layout/main-layout/main-layout.component.scss b/code/frontend/src/app/layout/main-layout/main-layout.component.scss index 4525da16..55bbb0c1 100644 --- a/code/frontend/src/app/layout/main-layout/main-layout.component.scss +++ b/code/frontend/src/app/layout/main-layout/main-layout.component.scss @@ -15,208 +15,7 @@ } } -// Main Sidebar Styling -.sidebar { - display: flex; - flex-direction: column; - width: 260px; - min-width: 260px; - height: 100vh; - background-color: var(--surface-overlay); - border-right: 1px solid var(--surface-border); - box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); - overflow-y: auto; - z-index: 10; - - // Top color line - .sidebar-top-line { - height: 3px; - background: var(--primary-color); - margin-bottom: 10px; - } - - // Hide on mobile screens - @media (max-width: 768px) { - display: none; - } -} - - // Top color line - .sidebar-top-line { - height: 3px; - background: linear-gradient(to right, #673ab7, #9b59b6); - margin-bottom: 10px; - } - - // Logo container - .logo-container { - display: flex; - align-items: center; - padding: 15px 20px; - margin-bottom: 5px; - - .logo { - display: flex; - align-items: center; - justify-content: center; - width: 40px; - height: 40px; - border-radius: 50%; - margin-right: 15px; - background-color: rgba(142, 68, 173, 0.1); - border: 1px solid rgba(142, 68, 173, 0.3); - animation: logo-glow 10s infinite ease-in-out; - - i { - font-size: 20px; - color: #a569bd; - } - } - - .logo-small { - display: none; - } - - h1 { - font-size: 20px; - font-weight: 700; - margin: 0; - background: linear-gradient(to right, #fff, #bbb); - -webkit-background-clip: text; - background-clip: text; - -webkit-text-fill-color: transparent; - } - } - - // Navigation menu - .nav-menu { - display: flex; - flex-direction: column; - padding: 5px 0 20px 0; - flex: 1; - - // Sponsor link - .sponsor-link { - margin-bottom: 15px; - border-bottom: 1px solid rgba(142, 68, 173, 0.15); - padding-bottom: 15px !important; - - .heart-icon i { - color: #ff4d6d !important; - animation: heart-pulse 7.2s infinite ease-in-out; - } - } - - // Nav groups - .nav-group { - margin-bottom: 15px; - - .nav-group-title { - font-size: 12px; - font-weight: 700; - color: rgba(142, 68, 173, 0.8); - text-transform: uppercase; - letter-spacing: 2px; - padding: 0 20px 8px; - margin-top: 10px; - margin-bottom: 5px; - border-bottom: 1px solid rgba(142, 68, 173, 0.2); - text-shadow: 0 0 10px rgba(142, 68, 173, 0.3); - } - } - - // Navigation items - .nav-item { - display: flex; - align-items: center; - padding: 10px 20px; - color: #e0e0e0; - text-decoration: none; - border-radius: 0 6px 6px 0; - margin: 2px 0 2px 0; - position: relative; - overflow: hidden; - transition: all 0.2s ease; - - .nav-icon-wrapper { - width: 32px; - height: 32px; - display: flex; - justify-content: center; - align-items: center; - margin-right: 15px; - border-radius: 8px; - background: rgba(46, 39, 56, 0.3); - border: 1px solid rgba(255, 255, 255, 0.05); - transition: all 0.2s ease; - - i { - font-size: 14px; - color: #e0e0e0; - } - } - - span { - white-space: nowrap; - font-size: 14px; - } - - &::before { - content: ''; - position: absolute; - left: 0; - top: 0; - height: 100%; - width: 3px; - background: transparent; - transition: all 0.2s ease; - } - - &:hover { - background: rgba(142, 68, 173, 0.15); - transform: translateX(2px); - - .nav-icon-wrapper { - background: rgba(142, 68, 173, 0.2); - transform: scale(1.05); - } - - &::before { - background: linear-gradient(to bottom, rgba(142, 68, 173, 0.4), rgba(103, 58, 183, 0.4)); - } - } - - &.active { - background: linear-gradient(to right, rgba(142, 68, 173, 0.9), rgba(103, 58, 183, 0.7)); - box-shadow: 0 2px 10px rgba(142, 68, 173, 0.3); - - .nav-icon-wrapper { - background: rgba(255, 255, 255, 0.15); - border-color: rgba(255, 255, 255, 0.2); - } - - &::before { - background: #fff; - } - } - } - } - -// Animation keyframes -@keyframes logo-glow { - 0% { box-shadow: 0 0 15px #8e44ad, 0 0 5px rgba(142, 68, 173, 0.4); } // Purple - 20% { box-shadow: 0 0 15px #9b59b6, 0 0 5px rgba(155, 89, 182, 0.4); } // Lighter purple - 40% { box-shadow: 0 0 15px #673ab7, 0 0 5px rgba(103, 58, 183, 0.4); } // Deep purple - 60% { box-shadow: 0 0 15px #5e35b1, 0 0 5px rgba(94, 53, 177, 0.4); } // Dark deep purple - 80% { box-shadow: 0 0 15px #7e57c2, 0 0 5px rgba(126, 87, 194, 0.4); } // Medium purple - 100% { box-shadow: 0 0 15px #8e44ad, 0 0 5px rgba(142, 68, 173, 0.4); } // Back to purple -} - -@keyframes heart-pulse { - 0% { color: #ff4d6d; text-shadow: 0 0 10px #ff4d6d, 0 0 20px #ff4d6d; } // Pink - 50% { color: #ff0a33; text-shadow: 0 0 15px #ff0a33, 0 0 25px #ff0a33; } // Red - 100% { color: #ff4d6d; text-shadow: 0 0 10px #ff4d6d, 0 0 20px #ff4d6d; } // Pink -} +// Animation keyframes (logo-glow and heart-pulse moved to sidebar-content component) @keyframes pulse-heart { 0% { @@ -375,22 +174,6 @@ // Deep styling overrides for PrimeNG components :host ::ng-deep { - // Mobile sidebar styling - .p-sidebar.p-component.mobile-sidebar { - background-color: var(--surface-overlay) !important; - border: none !important; - color: var(--text-color) !important; - box-shadow: 0 0 10px rgba(0, 0, 0, 0.2) !important; - - .p-sidebar-header { - display: none !important; - } - - .p-sidebar-content { - padding: 0 !important; - } - } - // Override Prime NG button styles .p-button { &.p-button-text { @@ -419,453 +202,15 @@ } } -// Mobile sidebar content -.mobile-sidebar-content { - display: flex; - flex-direction: column; - background-color: var(--surface-overlay); - color: var(--text-color); - height: 100%; - - .sidebar-top-line { - height: 3px; - background: var(--primary-color); - margin-bottom: 10px; - } - - .sidebar-header { - padding: 1rem; - display: flex; - align-items: center; - margin-bottom: 5px; - - .sidebar-logo { - display: flex; - align-items: center; - - .logo { - display: flex; - align-items: center; - justify-content: center; - width: 40px; - height: 40px; - border-radius: 50%; - margin-right: 15px; - background-color: rgba(142, 68, 173, 0.1); - border: 1px solid rgba(142, 68, 173, 0.3); - animation: logo-glow 10s infinite ease-in-out; - - i { - font-size: 20px; - color: #a569bd; - } - } - - .app-name { - font-size: 20px; - font-weight: 700; - margin-left: 0.5rem; - background: linear-gradient(to right, #fff, #bbb); - -webkit-background-clip: text; - background-clip: text; - -webkit-text-fill-color: transparent; - white-space: nowrap; - } - } - } - - .sidebar-nav { - padding: 5px 0 20px 0; - overflow-y: auto; - flex: 1; - - .sidebar-section-title { - font-size: 12px; - font-weight: 700; - color: rgba(142, 68, 173, 0.8); - text-transform: uppercase; - letter-spacing: 2px; - padding: 0 20px 8px; - margin-top: 10px; - margin-bottom: 5px; - border-bottom: 1px solid rgba(142, 68, 173, 0.2); - text-shadow: 0 0 10px rgba(142, 68, 173, 0.3); - } - - ul { - list-style: none; - } - - .sidebar-item { - display: flex; - align-items: center; - padding: 10px 20px; - color: #e0e0e0; - text-decoration: none; - border-radius: 0 6px 6px 0; - margin: 2px 0 2px 0; - position: relative; - overflow: hidden; - transition: all 0.2s ease; - - .item-icon-wrapper { - width: 32px; - height: 32px; - display: flex; - justify-content: center; - align-items: center; - margin-right: 15px; - border-radius: 8px; - background: rgba(46, 39, 56, 0.3); - border: 1px solid rgba(255, 255, 255, 0.05); - transition: all 0.2s ease; - } - - .item-icon { - font-size: 14px; - color: #e0e0e0; - } - - .item-label { - font-size: 14px; - white-space: nowrap; - } - - &::before { - content: ''; - position: absolute; - left: 0; - top: 0; - height: 100%; - width: 3px; - background: transparent; - transition: all 0.2s ease; - } - - &:hover { - background: rgba(142, 68, 173, 0.15); - transform: translateX(2px); - - .item-icon-wrapper { - background: rgba(142, 68, 173, 0.2); - transform: scale(1.05); - } - - &::before { - background: linear-gradient(to bottom, rgba(142, 68, 173, 0.4), rgba(103, 58, 183, 0.4)); - background-color: rgba(255, 255, 255, 0.1); - color: #ffffff; - font-weight: 600; - border-left: 3px solid #4299e1; - padding-left: calc(1rem - 3px); - - i { - color: #4299e1; - } - } - } - } - } - - .sponsor-section { - padding: 0.5rem 1rem 1rem; - margin-top: auto; - - .sponsor-link { - display: flex; - align-items: center; - padding: 0.75rem 1rem; - background-color: rgba(255, 255, 255, 0.05); - border-radius: 4px; - color: #ffffff; - text-decoration: none; - transition: background-color 0.2s; - - &:hover { - background-color: rgba(255, 255, 255, 0.1); - } - - i { - color: #ff5a5f; - margin-right: 0.75rem; - } - - span { - white-space: nowrap; - } - } - } -} - // Main layout .layout-main { display: flex; flex: 1; - // Sidebar - .sidebar { - width: 250px; - height: 100vh; - background: linear-gradient(135deg, #2c1a47 0%, #1a0e29 50%, #1e1230 75%, rgba(30, 18, 48, 0.95) 100%); - background-size: 100% 100%; - border-right: 1px solid rgba(142, 68, 173, 0.15); - box-shadow: 2px 0 15px rgba(0, 0, 0, 0.3); - display: flex; - flex-direction: column; - z-index: 1000; - flex-shrink: 0; - overflow-y: auto; - position: sticky; - top: 0; - transition: all 0.3s ease; - backdrop-filter: blur(5px); - - // Colored edge accents - &::before, - &::after { - content: ''; - position: absolute; - top: 0; - bottom: 0; - width: 1px; - background: linear-gradient(to bottom, rgba(142, 68, 173, 0.6), rgba(103, 58, 183, 0.6)); // Purple gradient - z-index: 2; - } - - &::before { - left: 0; - } - - &::after { - right: 0; - } - - .sidebar-top-line { - position: absolute; - top: 0; - left: 0; - right: 0; - height: 1px; - background: linear-gradient(90deg, rgba(142, 68, 173, 0.6), rgba(103, 58, 183, 0.6)); // Purple gradient - z-index: 2; - box-shadow: 0 0 8px rgba(142, 68, 173, 0.4); // Add subtle glow - } + // Sidebar container - all styling moved to sidebar-content component + // The sidebar-content component now handles all visual styling via :host selector - // Transitions for text elements in expanded state - .app-name, - .sidebar-section-title, - .sidebar-nav span, - .sponsor-link span { - opacity: 1; - visibility: visible; - width: auto; - max-width: 180px; - white-space: nowrap; - transition: all 0.3s ease; - } - - @media (max-width: 991px) { - display: none; - } - - &.collapsed { - width: 70px; - - .app-name, - .sidebar-section-title, - .sidebar-nav span, - .sponsor-link span { - opacity: 0; - visibility: hidden; - width: 0; - max-width: 0; - overflow: hidden; - transition: all 0.3s ease; - } - - .sidebar-nav li a { - padding: 0.75rem 0; - justify-content: center; - - i { - margin: 0 auto; - width: 100%; - display: flex; - justify-content: center; - } - } - - .sponsor-section .sponsor-link { - padding: 0.75rem 0; - justify-content: center; - - i { - margin: 0 auto; - width: 100%; - display: flex; - justify-content: center; - } - } - - .sidebar-footer { - justify-content: center; - } - } - - // Logo container - .logo-container { - display: flex; - align-items: center; - padding: 15px 20px 0px; - border-bottom: none; - margin-bottom: -15px; - position: relative; - - .logo { - display: flex; - align-items: center; - justify-content: center; - width: 60px; - height: 60px; - margin-right: 15px; - border-radius: 50%; - background-color: rgba(142, 68, 173, 0.1); - border: 1px solid rgba(142, 68, 173, 0.3); - animation: logo-glow 10s infinite ease-in-out; - transition: all 0.3s ease; - - i { - font-size: 30px; - color: #ffffff; - } - } - - .logo-small { - display: none; - } - - h1 { - font-size: 22px; - font-weight: 700; - margin: 0; - color: #fff; - text-shadow: 0 0 10px rgba(0, 0, 0, 0.5); - letter-spacing: 0.5px; - background: linear-gradient(to right, #fff, #bbb); - -webkit-background-clip: text; - background-clip: text; - -webkit-text-fill-color: transparent; - } - } - - // Sponsor section - .sponsor-section { - padding: 0.5rem 1rem 1rem; - - .sponsor-link { - display: flex; - align-items: center; - padding: 0.75rem 1rem; - background-color: rgba(255, 255, 255, 0.05); - border-radius: 4px; - color: #ffffff; - text-decoration: none; - transition: background-color 0.2s; - - &:hover { - background-color: rgba(255, 255, 255, 0.1); - } - - i { - color: #ff5a5f; - margin-right: 0.75rem; - } - } - } - - // Sidebar footer with toggle button - .sidebar-footer { - display: flex; - justify-content: flex-end; - padding: 1rem; - margin-top: auto; - - .sidebar-toggle { - color: #ffffff; - background-color: rgba(255, 255, 255, 0.1); - - &:hover { - background-color: rgba(255, 255, 255, 0.2); - } - } - } - } - - // Sidebar navigation - .sidebar-nav { - padding: 1rem 0; - overflow-y: auto; - flex: 1; - - .sidebar-section { - margin-bottom: 1.5rem; - - .sidebar-section-title { - padding: 0 1rem; - margin: 0 0 0.5rem 0; - font-size: 0.75rem; - font-weight: 600; - color: rgba(255, 255, 255, 0.5); - letter-spacing: 0.5px; - } - - ul { - list-style: none; - padding: 0; - margin: 0; - - li { - a { - display: flex; - align-items: center; - padding: 0.75rem 1rem; - color: rgba(255, 255, 255, 0.8); - text-decoration: none; - transition: background-color 0.2s; - - &:hover { - background-color: rgba(255, 255, 255, 0.05); - } - - i { - font-size: 1.25rem; - width: 1.5rem; - margin-right: 0.75rem; - text-align: center; - } - - span { - font-size: 0.95rem; - transition: opacity 0.2s ease, width 0.2s ease; - white-space: nowrap; - } - } - - &.active a { - background-color: rgba(255, 255, 255, 0.1); - color: #ffffff; - font-weight: 600; - border-left: 3px solid #4299e1; - padding-left: calc(1rem - 3px); - - i { - color: #4299e1; - } - } - } - } - } - } + // Sidebar navigation styles moved to sidebar-content component // Content area .layout-content { @@ -1196,39 +541,12 @@ transition: all 0.3s ease; } } - - @keyframes logo-glow { - 0% { box-shadow: 0 0 15px #8e44ad, 0 0 5px rgba(142, 68, 173, 0.4); } // Purple - 20% { box-shadow: 0 0 15px #9b59b6, 0 0 5px rgba(155, 89, 182, 0.4); } // Lighter purple - 40% { box-shadow: 0 0 15px #673ab7, 0 0 5px rgba(103, 58, 183, 0.4); } // Deep purple - 60% { box-shadow: 0 0 15px #5e35b1, 0 0 5px rgba(94, 53, 177, 0.4); } // Dark deep purple - 80% { box-shadow: 0 0 15px #7e57c2, 0 0 5px rgba(126, 87, 194, 0.4); } // Medium purple - 100% { box-shadow: 0 0 15px #8e44ad, 0 0 5px rgba(142, 68, 173, 0.4); } // Back to purple - } } } } } -// Mobile sidebar styling -.mobile-sidebar-content { - display: flex; - flex-direction: column; - height: 100%; - background: linear-gradient(135deg, #2c1a47 0%, #1a0e29 50%, #1e1230 75%, rgba(30, 18, 48, 0.95) 100%); - overflow-y: auto; - - .sidebar-top-line { - position: absolute; - top: 0; - left: 0; - right: 0; - height: 3px; - background: linear-gradient(90deg, rgba(142, 68, 173, 0.6), rgba(103, 58, 183, 0.6)); - z-index: 2; - box-shadow: 0 0 8px rgba(142, 68, 173, 0.4); - } -} +// Mobile sidebar styling moved to sidebar-content component /* Media queries for responsiveness */ @media screen and (max-width: 768px) { @@ -1252,16 +570,5 @@ } } - // Style PrimeNG mobile sidebar - :host ::ng-deep { - .p-sidebar.mobile-sidebar { - .p-sidebar-header { - display: none; // Hide the header since we're not using it - } - - .p-sidebar-content { - padding: 0; - } - } - } + // Drawer/Sidebar mobile styling is centralized in sidebar-content component } \ No newline at end of file diff --git a/code/frontend/src/app/layout/main-layout/main-layout.component.ts b/code/frontend/src/app/layout/main-layout/main-layout.component.ts index b3b9db0d..61dd3e33 100644 --- a/code/frontend/src/app/layout/main-layout/main-layout.component.ts +++ b/code/frontend/src/app/layout/main-layout/main-layout.component.ts @@ -1,4 +1,4 @@ -import { Component, inject, signal } from '@angular/core'; +import { Component, HostListener, inject, signal } from '@angular/core'; import { Router, RouterOutlet } from '@angular/router'; import { CommonModule } from '@angular/common'; import { Title } from '@angular/platform-browser'; @@ -9,7 +9,7 @@ import { ToolbarModule } from 'primeng/toolbar'; import { FormsModule } from '@angular/forms'; import { MenuModule } from 'primeng/menu'; import { SidebarModule } from 'primeng/sidebar'; -import { DrawerModule } from 'primeng/drawer'; + import { DividerModule } from 'primeng/divider'; import { RippleModule } from 'primeng/ripple'; import { ConfirmDialogModule } from 'primeng/confirmdialog'; @@ -29,7 +29,6 @@ import { ToastContainerComponent } from '../../shared/components/toast-container FormsModule, MenuModule, SidebarModule, - DrawerModule, DividerModule, RippleModule, ConfirmDialogModule, @@ -40,25 +39,15 @@ import { ToastContainerComponent } from '../../shared/components/toast-container styleUrl: './main-layout.component.scss' }) export class MainLayoutComponent { - // Mobile menu state - mobileSidebarVisible = signal(false); - // Inject router public router = inject(Router); constructor() {} /** - * Handles mobile navigation click events by closing the sidebar - */ - onMobileNavClick(): void { - this.mobileSidebarVisible.set(false); - } - - /** - * Toggle mobile sidebar visibility + * Toggle mobile sidebar visibility via sidebar component */ toggleMobileSidebar(): void { - this.mobileSidebarVisible.update(value => !value); + // This will be called via template reference } } diff --git a/code/frontend/src/app/layout/sidebar-content/sidebar-content.component.html b/code/frontend/src/app/layout/sidebar-content/sidebar-content.component.html index 35d838f2..eeb5ce2a 100644 --- a/code/frontend/src/app/layout/sidebar-content/sidebar-content.component.html +++ b/code/frontend/src/app/layout/sidebar-content/sidebar-content.component.html @@ -1,10 +1,7 @@
-

Cleanuparr

@@ -26,7 +23,7 @@ [@staggerItems]>