From 9238fc8d86175452ebd6dbe4ffc46a9b2fac8d45 Mon Sep 17 00:00:00 2001 From: 4gray Date: Sat, 29 Nov 2025 19:39:35 +0100 Subject: [PATCH] refactor(header): modernize header styles and remove unused module Update header component UI and streamline imports. - Remove MatToolbarModule import and module list entry because the toolbar styling is handled by local SCSS and the Angular Material toolbar is no longer required. - Rewrite header SCSS to introduce a .modern-header wrapper with consistent sizing, padding, alignment and a subtle bottom border. - Add layered ambient and depth effects: refined ::before ambient gradient (headerAmbience), ::after bottom accent, and adjusted keyframes for a gentler motion. - Refine home-header styles to target .modern-header and tune colors and gradients for a cohesive dark theme. - Rework .brand-block visuals: lighter glass effect, adjusted radii, blur, borders, hover transform, and shadowing for a modern elevated look. - Minor cleanup: remove legacy variables and comments; improve box-sizing, layout, and pointer-event handling to ensure expected interaction regions. These changes modernize the header's visual design, improve layout consistency across pages, and remove an unnecessary module import. --- apps/web/src/app/app.component.ts | 5 +- apps/web/src/app/home/home.component.scss | 2 +- .../components/header/header.component.html | 4 +- .../components/header/header.component.scss | 409 ++++++++++++------ .../components/header/header.component.ts | 2 - apps/web/src/styles.scss | 13 + 6 files changed, 301 insertions(+), 134 deletions(-) diff --git a/apps/web/src/app/app.component.ts b/apps/web/src/app/app.component.ts index 1efaef72b..a42953de3 100644 --- a/apps/web/src/app/app.component.ts +++ b/apps/web/src/app/app.component.ts @@ -1,4 +1,4 @@ -import { Component, inject, OnInit } from '@angular/core'; +import { Component, HostBinding, inject, OnInit } from '@angular/core'; import { MatDialog } from '@angular/material/dialog'; import { Router, RouterOutlet } from '@angular/router'; import { Actions, ofType } from '@ngrx/effects'; @@ -27,6 +27,9 @@ import { SearchResultsComponent } from './xtream-tauri/search-results/search-res imports: [RouterOutlet], }) export class AppComponent implements OnInit { + @HostBinding('class.macos-platform') get isMacOS() { + return window.electron && navigator.platform.toLowerCase().includes('mac'); + } private actions$ = inject(Actions); private dataService = inject(DataService); private dialog = inject(MatDialog); diff --git a/apps/web/src/app/home/home.component.scss b/apps/web/src/app/home/home.component.scss index 72585c820..c4b94498d 100644 --- a/apps/web/src/app/home/home.component.scss +++ b/apps/web/src/app/home/home.component.scss @@ -1,4 +1,4 @@ .recent-playlists { - height: calc(100vh - 100px); + height: calc(100vh - 71px); overflow: auto; } diff --git a/apps/web/src/app/shared/components/header/header.component.html b/apps/web/src/app/shared/components/header/header.component.html index 2056884f0..bf9697502 100644 --- a/apps/web/src/app/shared/components/header/header.component.html +++ b/apps/web/src/app/shared/components/header/header.component.html @@ -1,4 +1,4 @@ - +
} - +
diff --git a/apps/web/src/app/shared/components/header/header.component.scss b/apps/web/src/app/shared/components/header/header.component.scss index 59f0ce49d..2bfec560a 100644 --- a/apps/web/src/app/shared/components/header/header.component.scss +++ b/apps/web/src/app/shared/components/header/header.component.scss @@ -1,45 +1,62 @@ :host { - background: linear-gradient(135deg, #0a0a0b 0%, #1b1c1c 100%); + display: block; + width: 100%; +} + +.modern-header { + background: #131316; color: #fff; display: flex; + align-items: center; width: 100%; - --mat-toolbar-standard-height: 70px; - //padding-left: 80px; // Space for macOS traffic lights + height: 70px; + padding: 0 16px; app-region: drag; position: relative; overflow: hidden; -} + box-sizing: border-box; + border-bottom: 1px solid rgba(255, 255, 255, 0.03); -// Premium home page gradient - dark theme -:host.home-header { - background: linear-gradient( - 135deg, - #0f0c1d 0%, - #1a1428 25%, - #1e1535 50%, - #151121 75%, - #0d0a18 100% - ); - - // Subtle animated glow overlay + // Subtle depth layer &::before { content: ''; position: absolute; - top: -50%; - left: -50%; - width: 200%; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: linear-gradient( + 180deg, + rgba(255, 255, 255, 0.01) 0%, + rgba(255, 255, 255, 0) 100% + ); + pointer-events: none; + } +} + +// Refined home page styling - seamless with #131316 +:host.home-header .modern-header { + background: #131316; + + // Elegant ambient glow + &::before { + content: ''; + position: absolute; + top: -100%; + left: 0; + width: 100%; height: 200%; background: radial-gradient( - circle at 30% 50%, - rgba(139, 92, 246, 0.08) 0%, - rgba(99, 102, 241, 0.05) 25%, - transparent 50% + ellipse at 50% 0%, + rgba(99, 102, 241, 0.04) 0%, + rgba(139, 92, 246, 0.02) 30%, + transparent 60% ); - animation: headerGlow 15s ease-in-out infinite; + animation: headerAmbience 20s ease-in-out infinite; pointer-events: none; } - // Edge accent + // Refined bottom accent &::after { content: ''; position: absolute; @@ -50,62 +67,67 @@ background: linear-gradient( 90deg, transparent 0%, - rgba(139, 92, 246, 0.3) 20%, - rgba(99, 102, 241, 0.4) 50%, - rgba(139, 92, 246, 0.3) 80%, + rgba(139, 92, 246, 0.15) 50%, transparent 100% ); - opacity: 0.6; + opacity: 0.5; } } -@keyframes headerGlow { +@keyframes headerAmbience { 0%, 100% { - transform: translate(0, 0) rotate(0deg); - opacity: 1; + opacity: 0.3; + transform: translateY(0); } - 33% { - transform: translate(-10%, -5%) rotate(120deg); - opacity: 0.8; - } - 66% { - transform: translate(5%, 10%) rotate(240deg); - opacity: 0.9; + 50% { + opacity: 0.6; + transform: translateY(-5%); } } -// Compact brand block with pulsing logo +// Refined brand block with elegant glass effect .brand-block { display: flex; align-items: center; gap: 12px; padding: 0 16px 0 8px; - background: rgba(255, 255, 255, 0.03); - border-radius: 35px; - border: 1px solid rgba(255, 255, 255, 0.06); - backdrop-filter: blur(10px); - transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); - app-region: no-drag; // Allow interaction with brand block + background: rgba(255, 255, 255, 0.02); + border-radius: 32px; + border: 1px solid rgba(255, 255, 255, 0.04); + backdrop-filter: blur(12px); + transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1); + app-region: no-drag; position: relative; z-index: 1; + box-shadow: + 0 2px 8px rgba(0, 0, 0, 0.1), + inset 0 1px 0 rgba(255, 255, 255, 0.03); &:hover { - background: rgba(255, 255, 255, 0.05); - border-color: rgba(255, 255, 255, 0.1); + background: rgba(255, 255, 255, 0.04); + border-color: rgba(255, 255, 255, 0.08); + transform: translateY(-1px); + box-shadow: + 0 4px 12px rgba(0, 0, 0, 0.15), + inset 0 1px 0 rgba(255, 255, 255, 0.05); } } -// Enhanced brand block on home page - dark theme +// Enhanced brand block on home page - refined elegance :host.home-header .brand-block { - background: rgba(139, 92, 246, 0.08); - border-color: rgba(139, 92, 246, 0.15); - box-shadow: 0 4px 16px rgba(139, 92, 246, 0.1); + background: rgba(139, 92, 246, 0.04); + border-color: rgba(139, 92, 246, 0.08); + box-shadow: + 0 2px 12px rgba(139, 92, 246, 0.06), + inset 0 1px 0 rgba(139, 92, 246, 0.08); &:hover { - background: rgba(139, 92, 246, 0.12); - border-color: rgba(139, 92, 246, 0.25); - box-shadow: 0 6px 20px rgba(139, 92, 246, 0.15); + background: rgba(139, 92, 246, 0.08); + border-color: rgba(139, 92, 246, 0.15); + box-shadow: + 0 4px 16px rgba(139, 92, 246, 0.12), + inset 0 1px 0 rgba(139, 92, 246, 0.12); } } @@ -123,10 +145,11 @@ object-fit: contain; position: relative; z-index: 2; - filter: drop-shadow(0 2px 8px rgba(255, 59, 48, 0.3)); + filter: drop-shadow(0 2px 6px rgba(255, 59, 48, 0.25)); + transition: filter 0.3s ease; } - // Pulsing effect - like a live broadcast indicator + // Subtle ambient glow &::before { content: ''; position: absolute; @@ -134,37 +157,28 @@ height: 100%; background: radial-gradient( circle, - rgba(255, 59, 48, 0.4) 0%, + rgba(255, 59, 48, 0.15) 0%, + rgba(255, 59, 48, 0.05) 50%, transparent 70% ); border-radius: 50%; - animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; + animation: logoGlow 3s cubic-bezier(0.4, 0, 0.6, 1) infinite; } - &::after { - content: ''; - position: absolute; - width: 100%; - height: 100%; - background: radial-gradient( - circle, - rgba(255, 59, 48, 0.2) 0%, - transparent 70% - ); - border-radius: 50%; - animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite 0.5s; + .brand-block:hover & img { + filter: drop-shadow(0 2px 8px rgba(255, 59, 48, 0.4)); } } -@keyframes pulse { +@keyframes logoGlow { 0%, 100% { transform: scale(1); - opacity: 1; + opacity: 0.6; } 50% { - transform: scale(1.4); - opacity: 0; + transform: scale(1.15); + opacity: 1; } } @@ -174,17 +188,43 @@ justify-content: center; .title { - font-size: 1.1rem; + font-size: 1.05rem; font-weight: 600; - letter-spacing: -0.02em; - background: linear-gradient(135deg, #ffffff 0%, #e0e0e0 100%); - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; - background-clip: text; + letter-spacing: -0.015em; + color: rgba(255, 255, 255, 0.95); + transition: all 0.3s ease; + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2); + } + + .brand-block:hover & .title { + color: rgba(255, 255, 255, 1); + text-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); } } -// Modern centered search field +// Enhanced brand text on home page +:host.home-header .brand-text .title { + background: linear-gradient( + 135deg, + rgba(255, 255, 255, 0.95) 0%, + rgba(139, 92, 246, 0.8) 100% + ); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; + + .brand-block:hover & { + background: linear-gradient( + 135deg, + rgba(255, 255, 255, 1) 0%, + rgba(139, 92, 246, 1) 100% + ); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + } +} + +// Refined search field with elegant glass-morphism .search-container { flex: 1; max-width: 500px; @@ -192,68 +232,75 @@ position: relative; display: flex; align-items: center; - background: rgba(255, 255, 255, 0.04); - border: 1px solid rgba(255, 255, 255, 0.08); - border-radius: 24px; - padding: 0 20px; - height: 48px; - transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); - app-region: no-drag; // Allow search interaction + background: rgba(255, 255, 255, 0.02); + border: 1px solid rgba(255, 255, 255, 0.06); + border-radius: 20px; + padding: 0 18px; + height: 46px; + transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1); + app-region: no-drag; z-index: 1; + box-shadow: + 0 1px 3px rgba(0, 0, 0, 0.08), + inset 0 1px 0 rgba(255, 255, 255, 0.02); &:focus-within { - background: rgba(255, 255, 255, 0.06); - border-color: rgba(255, 59, 48, 0.4); + background: rgba(255, 255, 255, 0.04); + border-color: rgba(139, 92, 246, 0.3); box-shadow: - 0 0 0 3px rgba(255, 59, 48, 0.1), - 0 4px 16px rgba(0, 0, 0, 0.2); + 0 0 0 2px rgba(139, 92, 246, 0.08), + 0 2px 8px rgba(139, 92, 246, 0.12), + inset 0 1px 0 rgba(255, 255, 255, 0.04); transform: translateY(-1px); } &:hover:not(:focus-within) { - background: rgba(255, 255, 255, 0.05); - border-color: rgba(255, 255, 255, 0.12); + background: rgba(255, 255, 255, 0.03); + border-color: rgba(255, 255, 255, 0.1); } } -// Enhanced search field on home page +// Enhanced search field on home page - refined elegance :host.home-header .search-container { - background: rgba(139, 92, 246, 0.06); - border-color: rgba(139, 92, 246, 0.12); + background: rgba(139, 92, 246, 0.03); + border-color: rgba(139, 92, 246, 0.08); + box-shadow: + 0 1px 4px rgba(139, 92, 246, 0.04), + inset 0 1px 0 rgba(139, 92, 246, 0.04); &:focus-within { - background: rgba(139, 92, 246, 0.1); - border-color: rgba(139, 92, 246, 0.4); + background: rgba(139, 92, 246, 0.06); + border-color: rgba(139, 92, 246, 0.3); box-shadow: - 0 0 0 3px rgba(139, 92, 246, 0.15), - 0 4px 20px rgba(139, 92, 246, 0.2); - transform: translateY(-1px); + 0 0 0 2px rgba(139, 92, 246, 0.1), + 0 4px 16px rgba(139, 92, 246, 0.15), + inset 0 1px 0 rgba(139, 92, 246, 0.08); } &:hover:not(:focus-within) { - background: rgba(139, 92, 246, 0.08); - border-color: rgba(139, 92, 246, 0.2); + background: rgba(139, 92, 246, 0.05); + border-color: rgba(139, 92, 246, 0.12); } } :host.home-header .search-icon { - color: rgba(139, 92, 246, 0.6); + color: rgba(139, 92, 246, 0.5); .search-container:focus-within & { - color: rgba(139, 92, 246, 0.9); + color: rgba(139, 92, 246, 0.85); } } .search-icon { - color: rgba(255, 255, 255, 0.4); + color: rgba(255, 255, 255, 0.35); margin-right: 12px; - font-size: 22px; - width: 22px; - height: 22px; - transition: color 0.3s ease; + font-size: 20px; + width: 20px; + height: 20px; + transition: color 0.4s cubic-bezier(0.4, 0, 0.2, 1); .search-container:focus-within & { - color: rgba(255, 59, 48, 0.8); + color: rgba(139, 92, 246, 0.85); } } @@ -262,14 +309,15 @@ background: transparent; border: none; outline: none; - color: #ffffff; - font-size: 15px; + color: rgba(255, 255, 255, 0.95); + font-size: 14.5px; font-weight: 400; - letter-spacing: -0.01em; + letter-spacing: -0.005em; &::placeholder { - color: rgba(255, 255, 255, 0.3); + color: rgba(255, 255, 255, 0.25); font-weight: 400; + letter-spacing: 0; } &::-webkit-search-cancel-button { @@ -277,13 +325,14 @@ appearance: none; height: 16px; width: 16px; - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='rgba(255,255,255,0.4)'%3E%3Cpath d='M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z'/%3E%3C/svg%3E"); + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='rgba(255,255,255,0.35)'%3E%3Cpath d='M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z'/%3E%3C/svg%3E"); cursor: pointer; - opacity: 0.6; - transition: opacity 0.2s ease; + opacity: 0.5; + transition: all 0.3s ease; &:hover { opacity: 1; + transform: scale(1.1); } } } @@ -300,26 +349,130 @@ } .add-playlist-btn { - background-color: #3f51b5; - color: #fff; + background-color: rgba(139, 92, 246, 0.12) !important; + color: rgba(139, 92, 246, 1) !important; + border: 1px solid rgba(139, 92, 246, 0.2); + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); + + &:hover { + background-color: rgba(139, 92, 246, 0.2) !important; + border-color: rgba(139, 92, 246, 0.3); + box-shadow: 0 2px 8px rgba(139, 92, 246, 0.15); + } + + .mat-icon { + color: rgba(139, 92, 246, 1) !important; + } } .dropdown-menu-header { padding: 0 16px; margin: 8px 0; - font-size: 12px; - font-weight: 500; - color: rgba(255, 255, 255, 0.6); + font-size: 11px; + font-weight: 600; + color: rgba(255, 255, 255, 0.5); + letter-spacing: 0.05em; + text-transform: uppercase; } .active-sort { - background-color: rgb(48 48 48); + background-color: rgba(139, 92, 246, 0.12) !important; + position: relative; + + &::before { + content: ''; + position: absolute; + left: 0; + top: 50%; + transform: translateY(-50%); + width: 3px; + height: 60%; + background: rgba(139, 92, 246, 0.8); + border-radius: 0 2px 2px 0; + } } .check-icon { margin-left: 8px; } +// Refined Material button and icon overrides +.modern-header { + // Elegant icon styling + ::ng-deep .mat-icon { + color: rgba(255, 255, 255, 0.85) !important; + transition: color 0.3s ease; + } + + // Refined icon buttons with glass effect + ::ng-deep .mat-mdc-icon-button { + color: rgba(255, 255, 255, 0.85) !important; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); + + &:hover { + background-color: rgba(255, 255, 255, 0.06) !important; + + .mat-icon { + color: rgba(255, 255, 255, 1) !important; + } + } + + &:active { + background-color: rgba(255, 255, 255, 0.1) !important; + transform: scale(0.96); + } + } + + // Menu items + ::ng-deep .mat-mdc-menu-item { + color: rgba(255, 255, 255, 0.9) !important; + + .mat-icon { + color: rgba(255, 255, 255, 0.8) !important; + } + + span { + color: rgba(255, 255, 255, 0.9) !important; + } + + &:hover { + .mat-icon { + color: rgba(255, 255, 255, 1) !important; + } + } + } + + // Checkbox styling + ::ng-deep .mat-mdc-checkbox { + color: rgba(255, 255, 255, 0.9) !important; + + .mdc-checkbox__background { + border-color: rgba(255, 255, 255, 0.6) !important; + } + } +} + +// Home page - refined purple accent for icons +:host.home-header .modern-header { + ::ng-deep .mat-icon { + color: rgba(255, 255, 255, 0.85) !important; + } + + ::ng-deep .mat-mdc-icon-button { + &:hover { + background-color: rgba(139, 92, 246, 0.1) !important; + + .mat-icon { + color: rgba(139, 92, 246, 1) !important; + } + } + + &:active { + background-color: rgba(139, 92, 246, 0.15) !important; + } + } +} + // Responsive design @media (max-width: 899px) { .search-container { @@ -329,8 +482,8 @@ } @media (max-width: 599px) { - :host { - --mat-toolbar-standard-height: 64px; + .modern-header { + height: 64px; padding-left: 70px; // Reduced padding for smaller screens } diff --git a/apps/web/src/app/shared/components/header/header.component.ts b/apps/web/src/app/shared/components/header/header.component.ts index 1dcff104c..e99af2211 100644 --- a/apps/web/src/app/shared/components/header/header.component.ts +++ b/apps/web/src/app/shared/components/header/header.component.ts @@ -6,7 +6,6 @@ import { MatDialog } from '@angular/material/dialog'; import { MatDividerModule } from '@angular/material/divider'; import { MatIconModule } from '@angular/material/icon'; import { MatMenuModule } from '@angular/material/menu'; -import { MatToolbarModule } from '@angular/material/toolbar'; import { MatTooltipModule } from '@angular/material/tooltip'; import { ActivatedRoute, Router } from '@angular/router'; import { Store } from '@ngrx/store'; @@ -32,7 +31,6 @@ import { MatDividerModule, MatIconModule, MatMenuModule, - MatToolbarModule, MatTooltipModule, ReactiveFormsModule, TranslateModule, diff --git a/apps/web/src/styles.scss b/apps/web/src/styles.scss index 86846957d..be6494f3a 100644 --- a/apps/web/src/styles.scss +++ b/apps/web/src/styles.scss @@ -1,6 +1,19 @@ // @import 'themes/'; @import '@yangkghjh/videojs-aspect-ratio-panel/dist/videojs-aspect-ratio-panel.css'; +// macOS specific styles - space for traffic lights +app-root.macos-platform app-header .modern-header { + padding-left: 80px; +} + +app-root.macos-platform .current-playlist { + padding-top: 30px; +} + +app-root.macos-platform app-navigation .portal-status-container { + padding-top: 30px; +} + body, html { user-select: none;