Basic Dashboard #14
|
@ -1,41 +1,97 @@
|
|||
<div class="flex h-screen overflow-hidden">
|
||||
<!-- Sidebar -->
|
||||
<div
|
||||
[class]="
|
||||
isCollapsed
|
||||
? 'bg-primary w-20 transition-all duration-300 ease-in-out'
|
||||
: 'bg-primary w-48 transition-all duration-300 ease-in-out'
|
||||
"
|
||||
class="transform">
|
||||
<div class="p-5 text-primary-content">Logo</div>
|
||||
<ul>
|
||||
<li class="p-4" *ngFor="let item of menuItems">
|
||||
<span class="cursor-pointer text-primary-content" *ngIf="isCollapsed">
|
||||
{{ item.icon }}
|
||||
</span>
|
||||
<span
|
||||
class="cursor-pointer text-primary-content"
|
||||
*ngIf="!isCollapsed"
|
||||
(click)="toggleSubMenu(item)">
|
||||
{{ item.name }}
|
||||
</span>
|
||||
<ul
|
||||
*ngIf="!isCollapsed && item.open"
|
||||
class="transition-all duration-300 ease-in-out">
|
||||
<li
|
||||
class="pl-8 py-2 cursor-pointer text-primary-content"
|
||||
*ngFor="let subItem of item.subItems">
|
||||
{{ subItem }}
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<!-- Toggle Button -->
|
||||
<button class="p-2 text-xl" (click)="toggleSidebar()">
|
||||
{{ isCollapsed ? '👉' : '👈' }}
|
||||
</button>
|
||||
<div class="flex flex-col h-screen overflow-hidden">
|
||||
<!-- Header -->
|
||||
<header
|
||||
class="p-4 bg-primary text-primary-content flex items-center z-20 h-20 shadow-sm shadow-black/50">
|
||||
<div class="w-10 flex items-center justify-center">
|
||||
<label class="btn btn-ghost swap swap-rotate md:invisible">
|
||||
<input
|
||||
type="checkbox"
|
||||
(change)="toggleSidebar()"
|
||||
[checked]="!isCollapsed" />
|
||||
<!-- hamburger icon -->
|
||||
<svg
|
||||
class="swap-off fill-current"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 512 512">
|
||||
<path
|
||||
d="M64,384H448V341.33H64Zm0-106.67H448V234.67H64ZM64,128v42.67H448V128Z" />
|
||||
</svg>
|
||||
<!-- close icon -->
|
||||
<svg
|
||||
class="swap-on fill-current"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 512 512">
|
||||
<polygon
|
||||
points="400 145.49 366.51 112 256 222.51 145.49 112 112 145.49 222.51 256 112 366.51 145.49 400 256 289.49 366.51 400 400 366.51 289.49 256 400 145.49" />
|
||||
</svg>
|
||||
</label>
|
||||
</div>
|
||||
<div class="pl-4 flex-grow">
|
||||
<div>Logo</div>
|
||||
</div>
|
||||
<!-- Desktop toggle button -->
|
||||
<button class="hidden md:block" (click)="toggleDesktopSidebar()">
|
||||
{{ isDesktopCollapsed ? '👉' : '👈' }}
|
||||
</button>
|
||||
</header>
|
||||
|
||||
<!-- Main content -->
|
||||
<div class="flex-1 p-10 text-2xl font-bold">Hauptinhalt hier</div>
|
||||
<div class="flex flex-1 relative">
|
||||
<!-- Sidebar -->
|
||||
<div
|
||||
[class]="
|
||||
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>
|
||||
<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
|
||||
*ngIf="!isCollapsed"
|
||||
class="fixed inset-0 bg-black bg-opacity-50 z-10 md:hidden"
|
||||
(click)="toggleSidebar()"></div>
|
||||
|
||||
<!-- Main content -->
|
||||
<div class="flex-1 p-10 text-2xl font-bold">Hauptinhalt hier</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -4,10 +4,11 @@ import {
|
|||
Component,
|
||||
HostListener,
|
||||
} from '@angular/core';
|
||||
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
|
||||
|
||||
interface MenuItem {
|
||||
name: string;
|
||||
icon: string;
|
||||
icon: SafeHtml;
|
||||
subItems: string[];
|
||||
open?: boolean;
|
||||
}
|
||||
|
@ -23,21 +24,21 @@ interface MenuItem {
|
|||
})
|
||||
export class DashboardRootComponent {
|
||||
public isCollapsed: boolean = false;
|
||||
public isDesktopCollapsed: boolean = false;
|
||||
public showMobileMenu: boolean = false;
|
||||
public userHasInteracted: boolean = false;
|
||||
public menuItems: MenuItem[] = [
|
||||
{ name: 'Home', icon: '🏠', subItems: [] },
|
||||
{ name: 'About', icon: 'ℹ️', subItems: [] },
|
||||
{
|
||||
name: 'Services',
|
||||
icon: '🛠️',
|
||||
subItems: ['Web Design', 'SEO', 'Development'],
|
||||
open: false,
|
||||
name: 'Dashboard',
|
||||
icon: this.sanitizer
|
||||
.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" />
|
||||
</svg>`),
|
||||
subItems: [],
|
||||
},
|
||||
{ name: 'Contact', icon: '📞', subItems: [] },
|
||||
];
|
||||
|
||||
public constructor() {}
|
||||
public constructor(private sanitizer: DomSanitizer) {}
|
||||
|
||||
@HostListener('window:resize', ['$event'])
|
||||
public onResize(): void {
|
||||
|
@ -53,9 +54,14 @@ export class DashboardRootComponent {
|
|||
|
||||
public toggleSidebar(): void {
|
||||
this.isCollapsed = !this.isCollapsed;
|
||||
this.showMobileMenu = !this.isCollapsed;
|
||||
this.userHasInteracted = true;
|
||||
}
|
||||
|
||||
public toggleDesktopSidebar(): void {
|
||||
this.isDesktopCollapsed = !this.isDesktopCollapsed;
|
||||
}
|
||||
|
||||
public toggleSubMenu(item: any): void {
|
||||
if (item.subItems.length) {
|
||||
item.open = !item.open;
|
||||
|
|
Loading…
Reference in New Issue