Skip to content

Feat/header - #3

Merged
kamycoding merged 6 commits into
mainfrom
feat/header
Aug 3, 2026
Merged

Feat/header#3
kamycoding merged 6 commits into
mainfrom
feat/header

Conversation

@kamycoding

Copy link
Copy Markdown
Owner

No description provided.

Copilot AI review requested due to automatic review settings August 3, 2026 08:18
@kamycoding
kamycoding merged commit ee7a18e into main Aug 3, 2026
1 check passed

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a new responsive site header with desktop navigation and a mobile menu overlay, and wires up fragment/anchor scrolling to support in-page navigation.

Changes:

  • Implemented a feature-rich Header component (mobile menu, focus handling, scroll locking, navigation/social links, language toggle UI).
  • Enabled router anchor scrolling via withInMemoryScrolling({ anchorScrolling: 'enabled' }).
  • Added new logo/navigation/social/decoration SVG assets used by the header UI, while removing placeholder/previous page markup.

Reviewed changes

Copilot reviewed 7 out of 23 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/app/pages/home/home.html Removed the previous homepage hero text (now empty).
src/app/layout/header/header.ts Added header behavior (menu open/close, scroll lock, focus management, listeners).
src/app/layout/header/header.spec.ts Removed header unit tests.
src/app/layout/header/header.model.ts Added typed models for navigation + social link data.
src/app/layout/header/header.html Added full header + mobile navigation menu markup.
src/app/layout/header/header.css Header stylesheet referenced in PR metadata (no diff shown).
src/app/layout/footer/footer.html Removed placeholder footer content (now empty).
src/app/app.config.ts Enabled in-memory anchor scrolling for fragment navigation.
public/logo.svg Added site logo asset.
public/assets/icons/social/linkedin.svg Added LinkedIn social icon asset.
public/assets/icons/social/github.svg Added GitHub social icon asset.
public/assets/icons/social/email.svg Added email social icon asset.
public/assets/icons/navigation/menu-open.svg Added mobile “open menu” icon.
public/assets/icons/navigation/menu-close.svg Added mobile “close menu” icon.
public/assets/icons/navigation/menu-active.svg Added “active/open” menu icon (contains embedded raster data).
public/assets/icons/navigation/close-active.svg Added “active/pressed” close icon (contains embedded raster data).
public/assets/decorations/navigation/nav-hover-skills.svg Added desktop nav hover decoration for “Skills”.
public/assets/decorations/navigation/nav-hover-projects.svg Added desktop nav hover decoration for “Projects”.
public/assets/decorations/navigation/nav-hover-contact.svg Added desktop nav hover decoration for “Contact”.
public/assets/decorations/navigation/nav-hover-about.svg Added desktop nav hover decoration for “About me”.
public/assets/decorations/language-hover-en.svg Added language toggle hover decoration (EN).
public/assets/decorations/language-hover-de.svg Added language toggle hover decoration (DE).
Suppressed comments (1)

src/app/pages/home/home.html:1

  • The Home page template is now empty, so navigating to the root route ("/") will render only the global header/footer and no page content. If this content was not moved elsewhere, this is a functional regression.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +86 to +146
protected toggleLanguage(): void {
this.activeLanguage.update((language) => (language === 'en' ? 'de' : 'en'));
}

protected openMobileMenu(): void {
if (this.isMobileMenuOpen()) {
return;
}

this.isMobileMenuOpen.set(true);
this.lockBodyScroll();

afterNextRender(
() => {
if (this.isMobileMenuOpen()) {
this.closeMenuButton().nativeElement.focus({
preventScroll: true,
});
}
},
{
injector: this.injector,
},
);
}

protected closeMobileMenu(restoreFocus = true): void {
if (!this.isMobileMenuOpen()) {
return;
}

if (restoreFocus) {
this.openMenuButton().nativeElement.focus({
preventScroll: true,
});
}

this.isMobileMenuOpen.set(false);
this.restoreBodyScroll();
}

@HostListener('document:keydown.escape')
protected onEscape(): void {
if (!this.isMobileMenuOpen()) {
return;
}

this.closeMobileMenu();
}

@HostListener('window:resize')
protected onViewportResize(): void {
const isDesktop = this.document.defaultView?.matchMedia(DESKTOP_MEDIA_QUERY).matches ?? false;

if (isDesktop) {
this.closeMobileMenu(false);
}
}

ngOnDestroy(): void {
this.restoreBodyScroll();
Comment on lines +136 to +143
@HostListener('window:resize')
protected onViewportResize(): void {
const isDesktop = this.document.defaultView?.matchMedia(DESKTOP_MEDIA_QUERY).matches ?? false;

if (isDesktop) {
this.closeMobileMenu(false);
}
}

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9c1b12dd71

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +65 to +66
routerLink="/"
[fragment]="item.fragment"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Add targets for the navigation fragments

Every desktop and mobile navigation item routes to fragments such as /#about, but a repository-wide search finds no matching about, skills, projects, or contact element IDs, and the home template is now empty. Consequently, selecting any primary navigation item only changes the URL and cannot scroll to or display the requested section.

Useful? React with 👍 / 👎.

Comment on lines +86 to +88
protected toggleLanguage(): void {
this.activeLanguage.update((language) => (language === 'en' ? 'de' : 'en'));
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Make the language switch translate the interface

When a user selects DE, this handler only changes the switch's colors and knob position; all navigation labels, accessible labels, and other content remain hard-coded in English, with no translation service or language-dependent data elsewhere in the repository. The control therefore announces that the language was switched without changing the interface language.

Useful? React with 👍 / 👎.

Comment on lines +145 to +146
[attr.aria-hidden]="!isMobileMenuOpen()"
[attr.inert]="isMobileMenuOpen() ? null : ''"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep keyboard focus inside the open mobile menu

When the mobile menu is open, inert is removed only from the menu while the underlying mobile header remains focusable. From the initially focused close button, keyboard users can Shift+Tab through the menu logo and onto the obscured open-menu button, so focus escapes behind the overlay; the background should be made inert or focus should be trapped until the menu closes.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants