Commit 150d727

HPCesia <me@hpcesia.com>
2025-01-29 16:35:05
feat: support custom navbar button oncllick event
1 parent fad779e
Changed files (3)
src/components/Navbar.astro
@@ -25,7 +25,7 @@ if (!title) title = 'Astral Halo';
   <div id="nav-center" class="m-auto flex w-fit max-md:hidden">
     {
       navbarConfig.navbarCenterItems.map((item) => (
-        <Button href={item.href} onclick={item.onclick} title={i18n(item.text)} class="!px-4">
+        <Button href={item.href} title={i18n(item.text)} class="!px-4">
           <span class="text-xl tracking-wide">{i18n(item.text)}</span>
         </Button>
       ))
@@ -38,8 +38,11 @@ if (!title) title = 'Astral Halo';
           <Button
             class="nav-menu-item"
             href={item.href}
-            onclick={item.onclick}
             title={i18n(item.text)}
+            {...(item.onclick &&
+              (typeof item.onclick === 'string'
+                ? { onclick: item.onclick }
+                : { id: 'nav-' + item.onclick.id }))}
           >
             <Icon name={item.icon} class="text-2xl" />
           </Button>
@@ -52,8 +55,11 @@ if (!title) title = 'Astral Halo';
           <Button
             class="nav-menu-item"
             href={item.href}
-            onclick={item.onclick}
             title={i18n(item.text)}
+            {...(item.onclick &&
+              (typeof item.onclick === 'string'
+                ? { onclick: item.onclick }
+                : { id: 'nav-' + item.onclick.id }))}
           >
             <Icon name={item.icon} class="text-2xl" />
           </Button>
@@ -68,3 +74,20 @@ if (!title) title = 'Astral Halo';
   </div>
 </div>
 <div id="navbar-placeholder" class="pt-20"></div>
+
+<script>
+  import { navbarConfig } from '@/config';
+  const rightItems = [
+    navbarConfig.navbarRightItems.onlyWide,
+    navbarConfig.navbarRightItems.always,
+  ].flat();
+
+  document.addEventListener('astro:page-load', () => {
+    rightItems.forEach((item) => {
+      if (item.onclick && typeof item.onclick !== 'string') {
+        const element = document.getElementById('nav-' + item.onclick.id);
+        if (element) element.addEventListener('click', item.onclick.function);
+      }
+    });
+  });
+</script>
src/components/Sidebar.astro
@@ -1,5 +1,6 @@
 ---
 import { navbarConfig } from '@/config';
+import { i18n } from '@i18n/translation';
 import { Icon } from 'astro-icon/components';
 import Button from './widgets/Button.astro';
 import DarkModeButton from './widgets/DarkModeButton.astro';
@@ -23,12 +24,7 @@ import DarkModeButton from './widgets/DarkModeButton.astro';
     <div id="sidebar-menu-text-items">
       {
         navbarConfig.navbarCenterItems.map((item) => (
-          <Button
-            id="sidebar-menu-item"
-            href={item.href}
-            onclick={item.onclick}
-            title={item.text}
-          >
+          <Button id="sidebar-menu-item" href={item.href} title={i18n(item.text)}>
             <span class="text-xl">{item.text}</span>
           </Button>
         ))
@@ -40,8 +36,11 @@ import DarkModeButton from './widgets/DarkModeButton.astro';
           <Button
             id="sidebar-menu-item"
             href={item.href}
-            onclick={item.onclick}
-            title={item.text}
+            title={i18n(item.text)}
+            {...(item.onclick &&
+              (typeof item.onclick === 'string'
+                ? { onclick: item.onclick }
+                : { id: 'side-' + item.onclick.id }))}
           >
             <Icon name={item.icon} class="text-2xl" />
           </Button>
@@ -81,3 +80,17 @@ import DarkModeButton from './widgets/DarkModeButton.astro';
     });
   });
 </script>
+
+<script>
+  import { navbarConfig } from '@/config';
+  const rightItems = navbarConfig.navbarRightItems.onlyWide;
+
+  document.addEventListener('astro:page-load', () => {
+    rightItems.forEach((item) => {
+      if (item.onclick && typeof item.onclick !== 'string') {
+        const element = document.getElementById('side-' + item.onclick.id);
+        if (element) element.addEventListener('click', item.onclick.function);
+      }
+    });
+  });
+</script>
src/types/config.ts
@@ -20,15 +20,30 @@ export type ProfileConfig = {
 };
 
 export type NavbarConfig = {
-  navbarCenterItems: { text: string | I18nKey; href?: string; onclick?: string }[];
+  navbarCenterItems: { text: string | I18nKey; href?: string }[];
   navbarRightItems: {
     onlyWide: {
       icon: string;
       text: string | I18nKey;
       href?: string;
-      onclick?: string;
+      onclick?:
+        | string
+        | {
+            id: string;
+            function: (this: HTMLElement, ev: MouseEvent) => unknown;
+          };
+    }[];
+    always: {
+      icon: string;
+      text: string | I18nKey;
+      href?: string;
+      onclick?:
+        | string
+        | {
+            id: string;
+            function: (this: HTMLElement, ev: MouseEvent) => unknown;
+          };
     }[];
-    always: { icon: string; text?: string; href?: string; onclick?: string }[];
   };
 };