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'; import { MatChipsModule } from '@angular/material/chips'; import { MatBadgeModule } from '@angular/material/badge'; import { NAV_DESTINATIONS } from '../../models/nav.model'; /** * Adaptive Navigation Component — switches between desktop sidebar * and mobile header layouts using CSS media queries + JS breakpoint sync. * * 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 all layouts. */ @Component({ selector: 'app-adaptive-navigation', standalone: true, imports: [ RouterLink, RouterLinkActive, MatIconModule, MatButtonModule, MatChipsModule, MatBadgeModule, ], templateUrl: './adaptive-navigation.component.html', styleUrl: './adaptive-navigation.component.scss', changeDetection: ChangeDetectionStrategy.OnPush, }) export class AdaptiveNavigationComponent implements OnInit, OnDestroy { /** Navigation destinations shared with other nav components */ protected readonly destinations = NAV_DESTINATIONS; /** Whether the mobile drawer is open */ protected readonly mobileMenuOpen = signal(false); /** 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); } /** Close mobile menu (e.g. on nav) */ 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 } }