CUB-27: Responsive layout and adaptive navigation
All checks were successful
Dev Build / build-test (pull_request) Successful in 2m46s
All checks were successful
Dev Build / build-test (pull_request) Successful in 2m46s
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { ChangeDetectionStrategy, Component, signal } from '@angular/core';
|
||||
import { ChangeDetectionStrategy, Component, signal, HostListener, OnDestroy, OnInit } from '@angular/core';
|
||||
import { RouterLink, RouterLinkActive } from '@angular/router';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
@@ -8,13 +8,14 @@ import { NAV_DESTINATIONS } from '../../models/nav.model';
|
||||
|
||||
/**
|
||||
* Adaptive Navigation Component — switches between desktop sidebar
|
||||
* and mobile header layouts using CSS media queries.
|
||||
* and mobile header layouts using CSS media queries + JS breakpoint sync.
|
||||
*
|
||||
* Desktop (≥768px): 72px sidebar with full navigation items.
|
||||
* Mobile (<768px): 56px compact header with hamburger menu.
|
||||
* Per CUB-27 spec breakpoints:
|
||||
* Compact (0–599px): Mobile header + hamburger + bottom nav
|
||||
* Medium (600–1023px): Collapsed sidebar (icon-only)
|
||||
* Expanded (≥1024px): Expandable sidebar (hover/click)
|
||||
*
|
||||
* The LIVE status indicator is visible in both layouts.
|
||||
* Per spec Section 3.1 (kiosk) and 3.2 (mobile).
|
||||
* The LIVE status indicator is visible in all layouts.
|
||||
*/
|
||||
@Component({
|
||||
selector: 'app-adaptive-navigation',
|
||||
@@ -31,7 +32,7 @@ import { NAV_DESTINATIONS } from '../../models/nav.model';
|
||||
styleUrl: './adaptive-navigation.component.scss',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class AdaptiveNavigationComponent {
|
||||
export class AdaptiveNavigationComponent implements OnInit, OnDestroy {
|
||||
/** Navigation destinations shared with other nav components */
|
||||
protected readonly destinations = NAV_DESTINATIONS;
|
||||
|
||||
@@ -41,6 +42,22 @@ export class AdaptiveNavigationComponent {
|
||||
/** Live connection status */
|
||||
protected readonly isConnected = signal(true);
|
||||
|
||||
/** Responsive breakpoint state */
|
||||
protected readonly isMedium = signal(false);
|
||||
protected readonly isExpanded = signal(false);
|
||||
|
||||
private readonly COMPACT_MAX = 599;
|
||||
private readonly MEDIUM_MAX = 1023;
|
||||
|
||||
ngOnInit(): void {
|
||||
this.updateBreakpoint();
|
||||
}
|
||||
|
||||
@HostListener('window:resize')
|
||||
onResize(): void {
|
||||
this.updateBreakpoint();
|
||||
}
|
||||
|
||||
/** Toggle mobile menu */
|
||||
toggleMobileMenu(): void {
|
||||
this.mobileMenuOpen.update((v) => !v);
|
||||
@@ -50,4 +67,18 @@ export class AdaptiveNavigationComponent {
|
||||
closeMobileMenu(): void {
|
||||
this.mobileMenuOpen.set(false);
|
||||
}
|
||||
|
||||
private updateBreakpoint(): void {
|
||||
const w = window.innerWidth;
|
||||
this.isMedium.set(w >= this.COMPACT_MAX + 1 && w <= this.MEDIUM_MAX);
|
||||
this.isExpanded.set(w > this.MEDIUM_MAX);
|
||||
// Close mobile menu when switching to desktop
|
||||
if (w > this.COMPACT_MAX) {
|
||||
this.mobileMenuOpen.set(false);
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
// HostListener auto-unsubscribes
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user