add correct name and improve navbar

This commit is contained in:
2026-04-05 12:38:04 +02:00
parent 4510d9e72e
commit c767c0b1a0
9 changed files with 111 additions and 25 deletions

View File

@@ -25,6 +25,13 @@
z-index: 20; z-index: 20;
} }
.sidebar-header {
display: flex;
align-items: center;
justify-content: space-between;
gap: 0.75rem;
}
.brand { .brand {
color: #e6edf3; color: #e6edf3;
font-size: 1.05rem; font-size: 1.05rem;
@@ -63,6 +70,35 @@
outline: none; outline: none;
} }
.burger {
display: none;
width: 2.25rem;
height: 2.25rem;
border: 1px solid #30363d;
border-radius: 10px;
background: rgba(13, 17, 23, 0.65);
cursor: pointer;
padding: 0.25rem;
}
.burger span {
display: block;
width: 1.2rem;
height: 2px;
margin: 0.24rem auto;
background: #e6edf3;
}
.site-footer {
margin-top: 2rem;
text-align: center;
color: #8b949e;
}
.site-footer p {
margin: 0;
}
@media (max-width: 1320px) { @media (max-width: 1320px) {
.content { .content {
max-width: 1040px; max-width: 1040px;
@@ -79,3 +115,38 @@
flex-wrap: wrap; flex-wrap: wrap;
} }
} }
@media (max-width: 768px) {
.content {
padding-top: calc(6.5rem + env(safe-area-inset-top));
}
.sidebar {
position: fixed;
top: 0.75rem;
right: 0.75rem;
left: 0.75rem;
width: auto;
margin: 0;
gap: 0.6rem;
border-radius: 16px;
}
.subtitle {
display: none;
}
.burger {
display: inline-block;
}
.nav {
display: none;
flex-direction: column;
gap: 0.4rem;
}
.nav.nav-open {
display: flex;
}
}

View File

@@ -1,19 +1,34 @@
<div class="shell"> <div class="shell">
<main class="content"> <main class="content">
<router-outlet></router-outlet> <router-outlet></router-outlet>
<footer class="site-footer">
<p>(c) {{ currentYear }} Tim Kainz - Fullstack Developer (Angular - C# - Flutter)</p>
</footer>
</main> </main>
<aside class="sidebar"> <aside class="sidebar">
<a class="brand" routerLink="/home">Alex Carter</a> <div class="sidebar-header">
<p class="subtitle">Fullstack Developer</p> <a class="brand" routerLink="/home" (click)="closeMenu()">Tim Kainz</a>
<button
class="burger"
type="button"
aria-label="Toggle navigation"
[attr.aria-expanded]="isMenuOpen"
(click)="toggleMenu()"
>
<span></span>
<span></span>
<span></span>
</button>
</div>
<nav class="nav" aria-label="Primary"> <nav class="nav" aria-label="Primary" [class.nav-open]="isMenuOpen">
<a routerLink="/home" routerLinkActive="active" [routerLinkActiveOptions]="{ exact: true }">Home</a> <a routerLink="/home" routerLinkActive="active" [routerLinkActiveOptions]="{ exact: true }" (click)="closeMenu()">Home</a>
<a routerLink="/about" routerLinkActive="active">About</a> <a routerLink="/home" fragment="stack" (click)="closeMenu()">Tech Stack</a>
<a routerLink="/home" fragment="stack">Tech Stack</a> <a routerLink="/home" fragment="projects" (click)="closeMenu()">Projects</a>
<a routerLink="/home" fragment="projects">Projects</a> <a routerLink="/home" fragment="experience" (click)="closeMenu()">Experience</a>
<a routerLink="/home" fragment="experience">Experience</a> <a routerLink="/about" routerLinkActive="active" (click)="closeMenu()">About</a>
<a routerLink="/contact" routerLinkActive="active">Contact</a> <a routerLink="/contact" routerLinkActive="active" (click)="closeMenu()">Contact</a>
</nav> </nav>
</aside> </aside>
</div> </div>

View File

@@ -24,5 +24,6 @@ describe('App', () => {
const compiled = fixture.nativeElement as HTMLElement; const compiled = fixture.nativeElement as HTMLElement;
expect(compiled.querySelector('.sidebar')).toBeTruthy(); expect(compiled.querySelector('.sidebar')).toBeTruthy();
expect(compiled.querySelectorAll('.nav a').length).toBeGreaterThanOrEqual(4); expect(compiled.querySelectorAll('.nav a').length).toBeGreaterThanOrEqual(4);
expect(compiled.querySelector('.site-footer')).toBeTruthy();
}); });
}); });

View File

@@ -7,4 +7,15 @@ import { RouterLink, RouterLinkActive, RouterOutlet } from '@angular/router';
templateUrl: './app.html', templateUrl: './app.html',
styleUrl: './app.css' styleUrl: './app.css'
}) })
export class App {} export class App {
isMenuOpen = false;
readonly currentYear = new Date().getFullYear();
toggleMenu(): void {
this.isMenuOpen = !this.isMenuOpen;
}
closeMenu(): void {
this.isMenuOpen = false;
}
}

View File

@@ -3,7 +3,7 @@
<p class="eyebrow">About</p> <p class="eyebrow">About</p>
<h1>Fullstack developer crafting modern web, backend, and mobile products.</h1> <h1>Fullstack developer crafting modern web, backend, and mobile products.</h1>
<p class="lede"> <p class="lede">
I am Alex Carter, and I enjoy building software that feels clean, fast, and reliable from I am Tim Kainz, and I enjoy building software that feels clean, fast, and reliable from
the first screen to the last API call. the first screen to the last API call.
</p> </p>
</section> </section>

View File

@@ -161,12 +161,6 @@ h2 {
margin-top: 0.45rem; margin-top: 0.45rem;
} }
.footer {
margin-bottom: 0;
text-align: center;
color: #8b949e;
}
@media (max-width: 760px) { @media (max-width: 760px) {
.page-wrap { .page-wrap {
padding-top: 0.5rem; padding-top: 0.5rem;

View File

@@ -61,8 +61,4 @@
} }
</div> </div>
</section> </section>
<footer class="section footer">
<p>(c) {{ currentYear }} {{ hero.name }} - Fullstack Developer (Angular - C# - Flutter)</p>
</footer>
</div> </div>

View File

@@ -25,7 +25,7 @@ describe('Home', () => {
it('should render hero title and project section', () => { it('should render hero title and project section', () => {
const compiled = fixture.nativeElement as HTMLElement; const compiled = fixture.nativeElement as HTMLElement;
expect(compiled.querySelector('h1')?.textContent).toContain('Alex Carter'); expect(compiled.querySelector('h1')?.textContent).toContain('Tim Kainz');
expect(compiled.querySelector('#projects h2')?.textContent).toContain('Featured Projects'); expect(compiled.querySelector('#projects h2')?.textContent).toContain('Featured Projects');
expect(compiled.querySelector('.hero-cta a[routerlink="/about"]')).toBeTruthy(); expect(compiled.querySelector('.hero-cta a[routerlink="/about"]')).toBeTruthy();
}); });

View File

@@ -29,10 +29,8 @@ interface TimelineItem {
styleUrl: './home.css', styleUrl: './home.css',
}) })
export class Home { export class Home {
readonly currentYear = new Date().getFullYear();
readonly hero = { readonly hero = {
name: 'Alex Carter', name: 'Tim Kainz',
role: 'Fullstack Developer', role: 'Fullstack Developer',
intro: intro:
'I build polished web, backend, and mobile products with Angular, C#, and Flutter.', 'I build polished web, backend, and mobile products with Angular, C#, and Flutter.',