This commit is contained in:
99
src/app/core/layout/page-shell.component.ts
Normal file
99
src/app/core/layout/page-shell.component.ts
Normal file
@@ -0,0 +1,99 @@
|
||||
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||
import { CommonModule, NgOptimizedImage } from '@angular/common';
|
||||
import { RouterLink } from '@angular/router';
|
||||
import { SectionNavItem } from '../../shared/models/section-nav.model';
|
||||
import { ThemeToggleComponent } from '../../shared/ui/theme-toggle/theme-toggle.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-page-shell',
|
||||
standalone: true,
|
||||
imports: [CommonModule, RouterLink, ThemeToggleComponent, NgOptimizedImage],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
template: `
|
||||
<div
|
||||
class="min-h-screen bg-zinc-50 text-zinc-900 font-saira transition-colors duration-300 dark:bg-slate-950 dark:text-zinc-100"
|
||||
>
|
||||
<header
|
||||
class="sticky top-0 z-30 border-b border-zinc-200/80 bg-white/70 backdrop-blur transition-colors duration-300 dark:border-slate-900/60 dark:bg-slate-950/70"
|
||||
>
|
||||
<div
|
||||
class="mx-auto flex max-w-6xl items-center justify-between px-4 py-4 md:px-8"
|
||||
>
|
||||
<div class="flex items-center gap-3">
|
||||
<img
|
||||
ngSrc="/images/profile.jpg"
|
||||
width="40"
|
||||
height="40"
|
||||
priority
|
||||
alt="Dzanan"
|
||||
class="h-10 w-10 rounded-full object-cover ring-1 ring-emerald-600/20 transition-colors dark:ring-emerald-500/30"
|
||||
/>
|
||||
<div class="flex flex-col leading-tight">
|
||||
<span class="text-sm text-zinc-500 dark:text-zinc-400"
|
||||
>Senior Software Engineer</span
|
||||
>
|
||||
<span class="text-base font-semibold">Amar Džanan</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Desktop Nav & Toggle -->
|
||||
<div class="hidden items-center gap-4 md:flex">
|
||||
<nav class="flex items-center gap-2">
|
||||
@for (section of sections; track section.label) {
|
||||
<a
|
||||
[routerLink]="section.path || []"
|
||||
[fragment]="section.fragment"
|
||||
class="rounded-full px-3 py-2 text-sm font-medium text-zinc-600 transition hover:bg-zinc-100 hover:text-zinc-900 dark:text-zinc-200 dark:hover:bg-slate-900 dark:hover:text-white"
|
||||
>
|
||||
{{ section.label }}
|
||||
</a>
|
||||
}
|
||||
</nav>
|
||||
<div
|
||||
class="h-6 w-px bg-zinc-200 dark:bg-slate-800"
|
||||
aria-hidden="true"
|
||||
></div>
|
||||
<app-theme-toggle />
|
||||
</div>
|
||||
|
||||
<!-- Mobile Toggle & Menu Placeholder -->
|
||||
<div class="flex items-center gap-4 md:hidden">
|
||||
<app-theme-toggle />
|
||||
<span class="text-sm text-zinc-500 dark:text-zinc-400"
|
||||
>Navigate</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<main class="relative overflow-hidden opacity-0 animate-[fade-in-up_1s_ease-out_0.3s_forwards]">
|
||||
<div
|
||||
class="pointer-events-none absolute inset-0 opacity-60 transition-opacity duration-500 dark:opacity-60"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<div
|
||||
class="absolute inset-x-0 top-0 h-96 bg-[radial-gradient(circle_at_50%_20%,rgba(16,185,129,0.15),transparent_40%)] dark:bg-[radial-gradient(circle_at_50%_20%,rgba(16,185,129,0.2),transparent_40%)]"
|
||||
></div>
|
||||
<div
|
||||
class="absolute inset-y-0 right-0 w-1/2 bg-[radial-gradient(circle_at_80%_50%,rgba(59,130,246,0.1),transparent_35%)] dark:bg-[radial-gradient(circle_at_80%_50%,rgba(59,130,246,0.12),transparent_35%)]"
|
||||
></div>
|
||||
</div>
|
||||
<div class="relative">
|
||||
<ng-content />
|
||||
</div>
|
||||
</main>
|
||||
<footer
|
||||
class="border-t border-zinc-200/80 bg-white/80 transition-colors duration-300 dark:border-slate-900/60 dark:bg-slate-950/80"
|
||||
>
|
||||
<div
|
||||
class="mx-auto flex max-w-6xl flex-wrap items-center justify-between gap-4 px-4 py-6 text-sm text-zinc-500 dark:text-zinc-400 md:px-8"
|
||||
>
|
||||
<span>Built for clarity and craft.</span>
|
||||
<span class="text-zinc-600 dark:text-zinc-500">dzanan.net</span>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
`
|
||||
})
|
||||
export class PageShellComponent {
|
||||
@Input({ required: true }) sections: SectionNavItem[] = [];
|
||||
}
|
||||
Reference in New Issue
Block a user