Update Main Navigation
This commit is contained in:
parent
2548133558
commit
5246b374c4
|
@ -1,14 +1,89 @@
|
||||||
<div class="flex flex-col h-screen overflow-hidden">
|
<div class="flex h-screen overflow-hidden">
|
||||||
<!-- Header -->
|
<!-- Sidebar -->
|
||||||
<header
|
<div
|
||||||
class="p-4 bg-primary text-primary-content flex items-center z-20 h-20 shadow-sm shadow-black/50">
|
[class]="
|
||||||
<div class="w-10 flex items-center justify-center">
|
isCollapsed
|
||||||
<label class="btn btn-ghost swap swap-rotate md:invisible">
|
? 'bg-primary w-0 md:w-20 transition-all duration-300 ease-in-out'
|
||||||
|
: showMobileMenu
|
||||||
|
? 'bg-primary w-64 transition-all duration-300 ease-in-out'
|
||||||
|
: isDesktopCollapsed
|
||||||
|
? 'bg-primary w-48 md:w-16 transition-all duration-300 ease-in-out'
|
||||||
|
: 'bg-primary w-48 md:w-48 transition-all duration-300 ease-in-out'
|
||||||
|
"
|
||||||
|
class="transform h-full z-20 overflow-y-auto fixed md:relative">
|
||||||
|
<div
|
||||||
|
[ngClass]="showMobileMenu ? 'justify-center' : 'justify-between'"
|
||||||
|
class="p-1 w-full h-16 bg-base-100 flex items-center relative">
|
||||||
|
<div class="flex items-center justify-center h-full w-full">
|
||||||
|
<div class="flex items-center space-x-4">
|
||||||
|
@if (!isCollapsed && !isDesktopCollapsed) {
|
||||||
|
<div class="text-primary">Logo</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
@if (!isCollapsed && !showMobileMenu) {
|
||||||
|
<button
|
||||||
|
(click)="toggleDesktopSidebar()"
|
||||||
|
class="flex items-center justify-center w-10 h-10 rounded-full">
|
||||||
|
@if (isDesktopCollapsed) {
|
||||||
|
<svg
|
||||||
|
class="stroke-current text-primary w-6 h-6"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke-width="3">
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
d="m8.25 4.5 7.5 7.5-7.5 7.5" />
|
||||||
|
</svg>
|
||||||
|
} @else {
|
||||||
|
<svg
|
||||||
|
class="stroke-current text-primary w-6 h-6"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke-width="3">
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
d="M15.75 19.5 8.25 12l7.5-7.5" />
|
||||||
|
</svg>
|
||||||
|
}
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<ul class="m-1">
|
||||||
|
<li
|
||||||
|
class="hover:bg-accent-content cursor-pointer hover:text-accent text-primary-content rounded-btn"
|
||||||
|
*ngFor="let item of menuItems">
|
||||||
|
<div
|
||||||
|
class="flex justify-center p-2"
|
||||||
|
*ngIf="isDesktopCollapsed && !showMobileMenu">
|
||||||
|
<span class="p-1" [innerHTML]="item.icon"></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="flex items-center rounded-btn justify-between cursor-pointer px-1 py-2 hover:bg-accent-content hover:text-accent text-primary-content"
|
||||||
|
*ngIf="!isDesktopCollapsed || showMobileMenu">
|
||||||
|
<div class="flex items-center hover:bold">
|
||||||
|
<span [innerHTML]="item.icon" class="mx-2"></span>
|
||||||
|
<span>{{ item.name }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex flex-col flex-grow">
|
||||||
|
<header class="p-4 bg-primary text-primary-content flex items-center h-16">
|
||||||
|
<div class="w-10 flex items-center justify-center md:hidden">
|
||||||
|
<label class="btn btn-ghost swap swap-rotate">
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
(change)="toggleSidebar()"
|
(change)="toggleSidebar()"
|
||||||
[checked]="!isCollapsed" />
|
[checked]="!isCollapsed" />
|
||||||
<!-- hamburger icon -->
|
|
||||||
<svg
|
<svg
|
||||||
class="swap-off fill-current"
|
class="swap-off fill-current"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
@ -18,7 +93,6 @@
|
||||||
<path
|
<path
|
||||||
d="M64,384H448V341.33H64Zm0-106.67H448V234.67H64ZM64,128v42.67H448V128Z" />
|
d="M64,384H448V341.33H64Zm0-106.67H448V234.67H64ZM64,128v42.67H448V128Z" />
|
||||||
</svg>
|
</svg>
|
||||||
<!-- close icon -->
|
|
||||||
<svg
|
<svg
|
||||||
class="swap-on fill-current"
|
class="swap-on fill-current"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
@ -30,68 +104,17 @@
|
||||||
</svg>
|
</svg>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="pl-4 flex-grow">
|
|
||||||
<div>Logo</div>
|
|
||||||
</div>
|
|
||||||
<!-- Desktop toggle button -->
|
|
||||||
<button class="hidden md:block" (click)="toggleDesktopSidebar()">
|
|
||||||
{{ isDesktopCollapsed ? '👉' : '👈' }}
|
|
||||||
</button>
|
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<div class="flex flex-1 relative">
|
<div class="flex-grow p-10 text-2xl font-bold overflow-y-auto">
|
||||||
<!-- Sidebar -->
|
<p>isCollapsed: {{ isCollapsed }}</p>
|
||||||
<div
|
<p>showMobileMenu: {{ showMobileMenu }}</p>
|
||||||
[class]="
|
<p>isDesktopCollapsed: {{ isDesktopCollapsed }}</p>
|
||||||
isCollapsed
|
|
||||||
? 'bg-primary w-0 md:w-20 transition-all duration-300 ease-in-out'
|
|
||||||
: isDesktopCollapsed
|
|
||||||
? 'bg-primary w-48 md:w-20 transition-all duration-300 ease-in-out shadow-xl shadow-black/50'
|
|
||||||
: 'bg-primary w-48 md:w-48 transition-all duration-300 ease-in-out shadow-xl shadow-black/50'
|
|
||||||
"
|
|
||||||
class="transform absolute md:relative h-full z-20 overflow-y-auto">
|
|
||||||
<ul class="p-4">
|
|
||||||
<li class="px-1 py-2" *ngFor="let item of menuItems">
|
|
||||||
<span
|
|
||||||
class="cursor-pointer text-red text-primary-content block md:inline-block"
|
|
||||||
*ngIf="isDesktopCollapsed && !showMobileMenu"
|
|
||||||
[innerHTML]="item.icon"></span>
|
|
||||||
|
|
||||||
<div
|
|
||||||
class="flex items-center justify-between cursor-pointer text-primary-content"
|
|
||||||
*ngIf="!isDesktopCollapsed || showMobileMenu"
|
|
||||||
(click)="toggleSubMenu(item)">
|
|
||||||
<div class="flex items-center">
|
|
||||||
<span [innerHTML]="item.icon" class="mx-2"></span>
|
|
||||||
<span>{{ item.name }}</span>
|
|
||||||
</div>
|
</div>
|
||||||
<span
|
|
||||||
*ngIf="item.subItems && item.subItems.length > 0"
|
|
||||||
[class.rotate-90]="item.open"
|
|
||||||
class="transition-transform duration-300">
|
|
||||||
▶
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<ul
|
|
||||||
*ngIf="(!isDesktopCollapsed || showMobileMenu) && item.open"
|
|
||||||
class="mt-2 ml-4 transition-all duration-300 ease-in-out">
|
|
||||||
<li
|
|
||||||
class="py-2 cursor-pointer text-primary-content hover:bg-primary-focus rounded"
|
|
||||||
*ngFor="let subItem of item.subItems">
|
|
||||||
{{ subItem }}
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
*ngIf="!isCollapsed"
|
*ngIf="!isCollapsed"
|
||||||
class="fixed inset-0 bg-black bg-opacity-50 z-10 md:hidden"
|
class="fixed inset-0 bg-black bg-opacity-50 z-10 md:hidden"
|
||||||
(click)="toggleSidebar()"></div>
|
(click)="toggleSidebar()"></div>
|
||||||
|
|
||||||
<!-- Main content -->
|
|
||||||
<div class="flex-1 p-10 text-2xl font-bold">Hauptinhalt hier</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -3,14 +3,15 @@ import {
|
||||||
ChangeDetectionStrategy,
|
ChangeDetectionStrategy,
|
||||||
Component,
|
Component,
|
||||||
HostListener,
|
HostListener,
|
||||||
|
OnInit,
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
|
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
|
||||||
|
|
||||||
interface MenuItem {
|
interface MenuItem {
|
||||||
name: string;
|
name: string;
|
||||||
icon: SafeHtml;
|
icon: SafeHtml;
|
||||||
subItems: string[];
|
|
||||||
open?: boolean;
|
open?: boolean;
|
||||||
|
active?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
@ -22,7 +23,7 @@ interface MenuItem {
|
||||||
styleUrl: './dashboard-root.component.scss',
|
styleUrl: './dashboard-root.component.scss',
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
})
|
})
|
||||||
export class DashboardRootComponent {
|
export class DashboardRootComponent implements OnInit {
|
||||||
public isCollapsed: boolean = false;
|
public isCollapsed: boolean = false;
|
||||||
public isDesktopCollapsed: boolean = false;
|
public isDesktopCollapsed: boolean = false;
|
||||||
public showMobileMenu: boolean = false;
|
public showMobileMenu: boolean = false;
|
||||||
|
@ -34,37 +35,38 @@ export class DashboardRootComponent {
|
||||||
.bypassSecurityTrustHtml(`<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6">
|
.bypassSecurityTrustHtml(`<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="m2.25 12 8.954-8.955c.44-.439 1.152-.439 1.591 0L21.75 12M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25" />
|
<path stroke-linecap="round" stroke-linejoin="round" d="m2.25 12 8.954-8.955c.44-.439 1.152-.439 1.591 0L21.75 12M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25" />
|
||||||
</svg>`),
|
</svg>`),
|
||||||
subItems: [],
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
public constructor(private sanitizer: DomSanitizer) {}
|
public constructor(private sanitizer: DomSanitizer) {}
|
||||||
|
|
||||||
|
public ngOnInit(): void {
|
||||||
|
this.onResize();
|
||||||
|
}
|
||||||
|
|
||||||
@HostListener('window:resize', ['$event'])
|
@HostListener('window:resize', ['$event'])
|
||||||
public onResize(): void {
|
public onResize(): void {
|
||||||
if (!this.userHasInteracted) {
|
if (window.innerWidth >= 768) {
|
||||||
this.isCollapsed = window.innerWidth < 768;
|
this.showMobileMenu = false;
|
||||||
} else {
|
|
||||||
if (window.innerWidth > 768) {
|
|
||||||
this.isCollapsed = false;
|
this.isCollapsed = false;
|
||||||
this.userHasInteracted = false;
|
} else {
|
||||||
}
|
this.isDesktopCollapsed = false;
|
||||||
|
this.isCollapsed = true;
|
||||||
|
this.showMobileMenu = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public toggleSidebar(): void {
|
public toggleSidebar(): void {
|
||||||
this.isCollapsed = !this.isCollapsed;
|
if (window.innerWidth < 768) {
|
||||||
this.showMobileMenu = !this.isCollapsed;
|
this.showMobileMenu = !this.showMobileMenu;
|
||||||
|
this.isCollapsed = !this.showMobileMenu;
|
||||||
|
} else {
|
||||||
|
this.isDesktopCollapsed = !this.isDesktopCollapsed;
|
||||||
|
}
|
||||||
this.userHasInteracted = true;
|
this.userHasInteracted = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public toggleDesktopSidebar(): void {
|
public toggleDesktopSidebar(): void {
|
||||||
this.isDesktopCollapsed = !this.isDesktopCollapsed;
|
this.isDesktopCollapsed = !this.isDesktopCollapsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public toggleSubMenu(item: any): void {
|
|
||||||
if (item.subItems.length) {
|
|
||||||
item.open = !item.open;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue