]> danix's work - danix.xyz-2.git/commitdiff
feat: add header nav and hamburger menu styling with JS handlers
authorDanilo M. <redacted>
Thu, 16 Apr 2026 13:28:23 +0000 (15:28 +0200)
committerDanilo M. <redacted>
Thu, 16 Apr 2026 13:28:23 +0000 (15:28 +0200)
- Add header, nav-link, header-actions component CSS
- Add menu-overlay and menu-nav component CSS
- Update hamburger-menu.html with vanilla JS handlers:
  - openMenu/closeMenu functions
  - ESC key support
  - Click outside to close (backdrop click)
  - Menu link auto-close
  - Scroll lock when menu open
- Replace Alpine @click with id-based event listeners
- Rebuild CSS: main.min.css updated

Co-Authored-By: Claude Haiku 4.5 <redacted>
themes/danix-xyz-hacker/assets/css/main.css
themes/danix-xyz-hacker/assets/css/main.min.css
themes/danix-xyz-hacker/layouts/partials/hamburger-menu.html

index e15d7567a22cf330e15e7c911c0ad649c78b2082..50d5284c861165805aae164345ecc24baf10d3bb 100644 (file)
@@ -390,6 +390,40 @@ html.theme-light {
     @apply flex items-center justify-between gap-4;
   }
 
+  /* Header navigation styling */
+  .header {
+    @apply fixed top-0 left-0 right-0 z-40;
+  }
+
+  .header-nav {
+    @apply hidden md:flex items-center gap-6;
+  }
+
+  .nav-link {
+    @apply text-text hover:text-accent transition-colors;
+  }
+
+  .header-actions {
+    @apply flex items-center gap-4;
+  }
+
+  /* Mobile menu overlay */
+  .menu-overlay {
+    @apply fixed inset-0 bg-bg z-40 opacity-0 invisible transition-all duration-300;
+  }
+
+  .menu-overlay.active {
+    @apply opacity-100 visible;
+  }
+
+  .menu-nav {
+    @apply flex flex-col gap-4 p-6 text-lg font-semibold;
+  }
+
+  .menu-nav a {
+    @apply text-text hover:text-accent transition-colors;
+  }
+
   /* Article metadata styling (with icons) */
   .article-meta {
     @apply flex flex-wrap items-center gap-4 text-sm text-text-dim;
index 122dfcbdc3e56936fecfdb8f838a7a2cdd2e4cba..fac5cca04f88ab36af1d432d2080cf12363ac444 100644 (file)
@@ -1470,6 +1470,40 @@ article.border.border-border\/30.rounded-lg.card.group.bg-bg {
   }
 }
 
+/* Header navigation styling */
+
+.header {
+  position: fixed;
+  top: 0px;
+  left: 0px;
+  right: 0px;
+  z-index: 40;
+}
+
+/* Mobile menu overlay */
+
+.menu-overlay {
+  visibility: hidden;
+  position: fixed;
+  inset: 0px;
+  z-index: 40;
+  background-color: var(--bg);
+  opacity: 0;
+  transition-property: all;
+  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
+  transition-duration: 300ms;
+}
+
+article.border.border-border\/30.rounded-lg.overflow-hidden.group.menu-overlay {
+  border-color: var(--border);
+  box-shadow: 0 0 20px var(--accent-glow);
+}
+
+.menu-overlay.active {
+  visibility: visible;
+  opacity: 1;
+}
+
 /* Article metadata styling (with icons) */
 
 /* Hero typography with fluid sizing */
index 666db78c3db7f18dfd0d8d1b8f9a0815d0c0a848..4260456dd45736cf91490344ea47ddafa6065340 100644 (file)
@@ -1,17 +1,17 @@
 <div
   id="menu-overlay"
-  class="fixed inset-0 bg-black/50 backdrop-blur opacity-0 invisible transition-all duration-200 z-40"
+  class="fixed inset-0 bg-black/50 backdrop-blur opacity-0 invisible transition-all duration-300 z-40"
+  aria-hidden="true"
 >
   <div
     id="hamburger-menu"
-    aria-hidden="true"
     class="fixed top-0 right-0 h-screen w-full max-w-sm bg-bg border-l border-border overflow-y-auto transform translate-x-full transition-transform duration-300 z-50"
   >
     <!-- Close button -->
     <div class="flex items-center justify-between p-6 border-b border-border">
       <span class="font-bold text-lg text-accent font-oxanium">Menu</span>
       <button
-        @click="closeMenu()"
+        id="menu-close"
         aria-label="{{ i18n "closeMenu" }}"
         class="p-2 hover:bg-surface rounded transition-colors"
       >
   </div>
 </div>
 
+<script>
+  document.addEventListener('DOMContentLoaded', () => {
+    const menuToggle = document.getElementById('menu-toggle');
+    const menuClose = document.getElementById('menu-close');
+    const menuOverlay = document.getElementById('menu-overlay');
+    const hamburgerMenu = document.getElementById('hamburger-menu');
+
+    const openMenu = () => {
+      menuOverlay.classList.remove('opacity-0', 'invisible');
+      hamburgerMenu.classList.remove('translate-x-full');
+      menuOverlay.setAttribute('aria-hidden', 'false');
+      document.body.style.overflow = 'hidden';
+      menuToggle.setAttribute('aria-expanded', 'true');
+    };
+
+    const closeMenu = () => {
+      menuOverlay.classList.add('opacity-0', 'invisible');
+      hamburgerMenu.classList.add('translate-x-full');
+      menuOverlay.setAttribute('aria-hidden', 'true');
+      document.body.style.overflow = '';
+      menuToggle.setAttribute('aria-expanded', 'false');
+    };
+
+    // Toggle button click
+    if (menuToggle) {
+      menuToggle.addEventListener('click', (e) => {
+        e.stopPropagation();
+        if (menuOverlay.classList.contains('opacity-0')) {
+          openMenu();
+        } else {
+          closeMenu();
+        }
+      });
+    }
+
+    // Close button click
+    if (menuClose) {
+      menuClose.addEventListener('click', closeMenu);
+    }
+
+    // Close on ESC key
+    document.addEventListener('keydown', (e) => {
+      if (e.key === 'Escape' && !menuOverlay.classList.contains('opacity-0')) {
+        closeMenu();
+      }
+    });
+
+    // Close when clicking menu links
+    const menuLinks = hamburgerMenu.querySelectorAll('a');
+    menuLinks.forEach(link => {
+      link.addEventListener('click', closeMenu);
+    });
+
+    // Close when clicking the overlay (but not the menu panel)
+    menuOverlay.addEventListener('click', (e) => {
+      if (e.target === menuOverlay) {
+        closeMenu();
+      }
+    });
+  });
+</script>