From bb5f51d8a8676f7babe5eb6477d4ea398be3fe64 Mon Sep 17 00:00:00 2001 From: chris Date: Tue, 11 Nov 2025 22:50:54 +0100 Subject: [PATCH] sort of working drawer menu (wip) --- .../shell/drawer/drawer.component.html | 14 +- .../shell/drawer/drawer.component.scss | 141 ++++++++++++++++-- .../shell/drawer/drawer.component.ts | 42 +++++- .../app/components/shell/shell.component.scss | 18 ++- 4 files changed, 197 insertions(+), 18 deletions(-) diff --git a/src/angular/frontend/src/app/components/shell/drawer/drawer.component.html b/src/angular/frontend/src/app/components/shell/drawer/drawer.component.html index 6a1ac2a..be07837 100644 --- a/src/angular/frontend/src/app/components/shell/drawer/drawer.component.html +++ b/src/angular/frontend/src/app/components/shell/drawer/drawer.component.html @@ -1,7 +1,17 @@ -
- +
+
+ +
+
diff --git a/src/angular/frontend/src/app/components/shell/drawer/drawer.component.scss b/src/angular/frontend/src/app/components/shell/drawer/drawer.component.scss index e43a9de..63723de 100644 --- a/src/angular/frontend/src/app/components/shell/drawer/drawer.component.scss +++ b/src/angular/frontend/src/app/components/shell/drawer/drawer.component.scss @@ -1,28 +1,148 @@ :host { display: flex; - height: 100%; overflow: auto; + --transition-duration: .3s; + --menu-trasition-duration: calc(var(--transition-duration) / 2); + + .material-symbols-outlined.collapsed-icon { + display: none; + } + .material-symbols-outlined.open-icon { + display: inline-block; + } + + &:has(.drawer-wrapper.collapsed) { + .material-symbols-outlined.collapsed-icon { + display: inline-block; + } + .material-symbols-outlined.open-icon { + display: none; + } + } + + &:has(.open-icon.active) { + + // todo fix when closing drawer animation is missing because all these styles are gone + + --menu-trasition-duration: .3s; + + @media (max-width: 768px) { + .drawer-wrapper { + display: block; + + &.ready { + .drawer-container { + @starting-style { + width: 0; + display: block; + padding-inline: 0; + } + } + } + } + .drawer-container { + display: block; + z-index: 1000; + position: absolute; + left: 0; + top: 0; + width: 250px; + height: 100dvh; + overflow: hidden; + min-width: 0; + + transition: + width var(--transition-duration) ease-in-out, + padding-inline var(--transition-duration) ease-in-out, + display var(--transition-duration) ease-in-out; + + transition-behavior: allow-discrete; + } + .main-content-container { + .menu-button { + top: calc(5rem - 1rem); + left: calc(250px - 1rem); + } + } + } + + } + + .drawer-wrapper { + height: 100%; + + flex-shrink: 0; + + width: 250px; + display: block; + + overflow: hidden; + + transition: + width var(--transition-duration) ease-in-out, + display var(--transition-duration) ease-in-out; + + transition-behavior: allow-discrete; + + &.ready { + @starting-style { + width: 0; + display: block; + } + } + + @media (max-width: 768px) { + width: 0; + display: none; + } + } + .drawer-container { + + height: 100%; display: flex; flex-direction: column; padding: 1rem; - } - - .main-content-container{ - display: flex; - flex-direction: column; - padding: 1rem 0 0 1rem; - } - - .drawer-container { background-color: var(--neutral-70); + + box-sizing: border-box; + min-width: fit-content; } .main-content-container { + display: flex; + flex-direction: column; + padding: 1rem 0 0 1rem; + + position: relative; + flex-grow: 1; + .menu-button { + position: absolute; + padding: .3333333rem; + border-radius: 50%; + z-index: 9999; + top: calc(5rem - 1rem); + left: -1rem; + width: 2rem; + height: 2rem; + + transition: top var(--menu-trasition-duration) ease-out, left var(--menu-trasition-duration) ease-out; + + @media (max-width: 768px) { + top: calc(2.5rem - 1rem); + left: 1rem; + } + + .material-symbols-outlined { + font-size: 1.3333333rem; + font-weight: 700; + } + } + .top-nav-breadcrumb-container, .top-nav-container { margin-right: 1rem; } @@ -39,7 +159,6 @@ padding-right: 1rem; flex-grow: 1; overflow: auto; - } } } diff --git a/src/angular/frontend/src/app/components/shell/drawer/drawer.component.ts b/src/angular/frontend/src/app/components/shell/drawer/drawer.component.ts index 735899f..811078e 100644 --- a/src/angular/frontend/src/app/components/shell/drawer/drawer.component.ts +++ b/src/angular/frontend/src/app/components/shell/drawer/drawer.component.ts @@ -1,14 +1,48 @@ -import { Component } from '@angular/core'; -import {RouterOutlet} from '@angular/router'; +import {AfterViewInit, Component, inject, OnInit, signal} from '@angular/core'; +import {NavigationEnd, Router, RouterOutlet} from '@angular/router'; +import {NgClass} from '@angular/common'; @Component({ selector: 'app-drawer', imports: [ - RouterOutlet + RouterOutlet, + NgClass ], templateUrl: './drawer.component.html', styleUrl: './drawer.component.scss' }) -export class DrawerComponent { +export class DrawerComponent implements AfterViewInit, OnInit { + protected viewInitialized = false; + protected isCollapsed = signal(true); + private router = inject(Router); + + constructor() { + this.router.events.subscribe((event) => { + if (!this.isDesktop() && !this.isCollapsed() && event instanceof NavigationEnd) { + this.isCollapsed.set(true); + } + }); + } + + ngOnInit(): void { + if (this.isDesktop()) { + this.isCollapsed.set(false); + } + } + + ngAfterViewInit(): void { + requestAnimationFrame(() => { + this.viewInitialized = true; + }) + } + + handleMenuButton(_: PointerEvent) { + this.isCollapsed.update(x => !x); + } + + private isDesktop(): boolean { + return window.innerWidth > 768 + } } + diff --git a/src/angular/frontend/src/app/components/shell/shell.component.scss b/src/angular/frontend/src/app/components/shell/shell.component.scss index 858d656..4f7cdd0 100644 --- a/src/angular/frontend/src/app/components/shell/shell.component.scss +++ b/src/angular/frontend/src/app/components/shell/shell.component.scss @@ -9,6 +9,17 @@ .title { font-size: 2rem; font-weight: bold; + + display: flex; + align-items: center; + + margin-left: 0; + + transition: margin-left var(--menu-trasition-duration) ease-out; + + @media (max-width: 768px) { + margin-left: 3rem; + } } app-nav-profile { margin-left: auto; @@ -21,9 +32,14 @@ .logo { $height: 3rem; height: $height; - width: #{$height * 3.356876171875}; + width: 100%; padding-bottom: 1rem; border-bottom: 1px solid var(--neutral-60); + + & ::ng-deep .icon { + height: $height; + width: #{$height * 3.356876171875}; + } } .nav-links {