@sofidevo/astro-dynamic-header 1.0.12 → 1.0.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/Header.astro +0 -31
- package/src/MobileNav.astro +89 -63
- package/src/hamburger.ts +20 -6
package/package.json
CHANGED
package/src/Header.astro
CHANGED
|
@@ -39,37 +39,6 @@ const {
|
|
|
39
39
|
} = Astro.props;
|
|
40
40
|
---
|
|
41
41
|
|
|
42
|
-
<script>
|
|
43
|
-
class HamburgerController {
|
|
44
|
-
private hamburgerBtn: HTMLElement | null;
|
|
45
|
-
private mobileMenu: HTMLElement | null;
|
|
46
|
-
|
|
47
|
-
constructor() {
|
|
48
|
-
this.hamburgerBtn = document.getElementById("hamburger-btn");
|
|
49
|
-
this.mobileMenu = document.getElementById("mobile-header-menu");
|
|
50
|
-
this.init();
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
private init(): void {
|
|
54
|
-
if (this.hamburgerBtn && this.mobileMenu) {
|
|
55
|
-
this.hamburgerBtn.addEventListener("click", () => this.toggleMenu());
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
private toggleMenu(): void {
|
|
60
|
-
if (this.hamburgerBtn && this.mobileMenu) {
|
|
61
|
-
this.hamburgerBtn.classList.toggle("is-active");
|
|
62
|
-
this.mobileMenu.classList.toggle("is-active");
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// Auto-initialize when DOM is ready
|
|
68
|
-
document.addEventListener('DOMContentLoaded', () => {
|
|
69
|
-
new HamburgerController();
|
|
70
|
-
});
|
|
71
|
-
</script>
|
|
72
|
-
|
|
73
42
|
<div class={`header__container header__container--${headerType}`} style={`z-index: ${zIndex};`}>
|
|
74
43
|
<header class={`header header--${headerType}`} style={`background-color: ${backgroundColor}; backdrop-filter: ${backdropBlur}; -webkit-backdrop-filter: ${backdropBlur};`}>
|
|
75
44
|
<a href={homeUrl}>
|
package/src/MobileNav.astro
CHANGED
|
@@ -10,7 +10,6 @@ export interface Props {
|
|
|
10
10
|
submenu?: Array<{
|
|
11
11
|
link: string;
|
|
12
12
|
text: string;
|
|
13
|
-
|
|
14
13
|
}>;
|
|
15
14
|
}>;
|
|
16
15
|
}>;
|
|
@@ -19,78 +18,97 @@ export interface Props {
|
|
|
19
18
|
accentColor?: string;
|
|
20
19
|
}
|
|
21
20
|
|
|
22
|
-
const
|
|
21
|
+
const { type } = Astro.props;
|
|
23
22
|
|
|
24
23
|
const {
|
|
25
24
|
menuItems = [],
|
|
26
25
|
showHomeLink = true,
|
|
27
26
|
homeText = "Home",
|
|
28
|
-
accentColor = "var(--light-spot-color, #00ffff)"
|
|
27
|
+
accentColor = "var(--light-spot-color, #00ffff)",
|
|
29
28
|
} = Astro.props;
|
|
30
29
|
|
|
31
30
|
const pagePathname = Astro.url.pathname;
|
|
32
31
|
---
|
|
33
32
|
|
|
34
|
-
<nav
|
|
33
|
+
<nav
|
|
34
|
+
class={`mobile-header__menu mobile-header__menu--${type}`}
|
|
35
|
+
id="mobile-header-menu"
|
|
36
|
+
style={`--mobile-accent-color: ${accentColor};`}
|
|
37
|
+
>
|
|
35
38
|
<ol class="mobile-menu">
|
|
36
|
-
{
|
|
37
|
-
|
|
38
|
-
<
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
{item.submenu ? (
|
|
46
|
-
<details class="mobile-details">
|
|
47
|
-
<summary class="menu__summary">
|
|
48
|
-
{item.text}
|
|
49
|
-
<iconify-icon
|
|
50
|
-
class="iconify-arrow"
|
|
51
|
-
icon="codicon:triangle-down"
|
|
52
|
-
width="15"
|
|
53
|
-
height="15"
|
|
54
|
-
style={`color: ${accentColor};`}
|
|
55
|
-
/>
|
|
56
|
-
</summary>
|
|
57
|
-
<ol class="mobile-submenu">
|
|
58
|
-
{item.submenu.map((sub) => (
|
|
59
|
-
<li>
|
|
60
|
-
{sub.submenu && sub.submenu.length > 0 ? (
|
|
61
|
-
<details class="mobile-details">
|
|
62
|
-
<summary class="menu__summary">
|
|
63
|
-
{sub.text}
|
|
64
|
-
<iconify-icon
|
|
65
|
-
class="iconify-arrow"
|
|
66
|
-
icon="codicon:triangle-down"
|
|
67
|
-
width="15"
|
|
68
|
-
height="15"
|
|
69
|
-
style={`color: ${accentColor};`}
|
|
70
|
-
/>
|
|
71
|
-
</summary>
|
|
72
|
-
<ol class="mobile-subsubmenu">
|
|
73
|
-
{sub.submenu.map((subsub) => (
|
|
74
|
-
<li class="mobile-submenu__item secondary">
|
|
75
|
-
<a class="menu__link mobile-menu__link" href={subsub.link}>{subsub.text}</a>
|
|
76
|
-
</li>
|
|
77
|
-
))}
|
|
78
|
-
</ol>
|
|
79
|
-
</details>
|
|
80
|
-
) : (
|
|
81
|
-
<a class="menu__link mobile-menu__link" href={sub.link}>{sub.text}</a>
|
|
82
|
-
)}
|
|
83
|
-
</li>
|
|
84
|
-
))}
|
|
85
|
-
</ol>
|
|
86
|
-
</details>
|
|
87
|
-
) : (
|
|
88
|
-
<a class="mobile-menu__link" href={item.link}>
|
|
89
|
-
{item.text}
|
|
39
|
+
{
|
|
40
|
+
showHomeLink && pagePathname !== "/" && (
|
|
41
|
+
<li class="header__item mobile-header__item">
|
|
42
|
+
<a
|
|
43
|
+
class="menu__link mobile-menu__link"
|
|
44
|
+
href="/"
|
|
45
|
+
data-astro-prefetch="hover"
|
|
46
|
+
>
|
|
47
|
+
{homeText}
|
|
90
48
|
</a>
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
49
|
+
</li>
|
|
50
|
+
)
|
|
51
|
+
}
|
|
52
|
+
{
|
|
53
|
+
menuItems.map((item) => (
|
|
54
|
+
<li>
|
|
55
|
+
{item.submenu ? (
|
|
56
|
+
<details class="mobile-details">
|
|
57
|
+
<summary class="menu__summary">
|
|
58
|
+
{item.text}
|
|
59
|
+
<iconify-icon
|
|
60
|
+
class="iconify-arrow"
|
|
61
|
+
icon="codicon:triangle-down"
|
|
62
|
+
width="15"
|
|
63
|
+
height="15"
|
|
64
|
+
style={`color: ${accentColor};`}
|
|
65
|
+
/>
|
|
66
|
+
</summary>
|
|
67
|
+
<ol class="mobile-submenu">
|
|
68
|
+
{item.submenu.map((sub) => (
|
|
69
|
+
<li>
|
|
70
|
+
{sub.submenu && sub.submenu.length > 0 ? (
|
|
71
|
+
<details class="mobile-details">
|
|
72
|
+
<summary class="menu__summary">
|
|
73
|
+
{sub.text}
|
|
74
|
+
<iconify-icon
|
|
75
|
+
class="iconify-arrow"
|
|
76
|
+
icon="codicon:triangle-down"
|
|
77
|
+
width="15"
|
|
78
|
+
height="15"
|
|
79
|
+
style={`color: ${accentColor};`}
|
|
80
|
+
/>
|
|
81
|
+
</summary>
|
|
82
|
+
<ol class="mobile-subsubmenu">
|
|
83
|
+
{sub.submenu.map((subsub) => (
|
|
84
|
+
<li class="mobile-submenu__item secondary">
|
|
85
|
+
<a
|
|
86
|
+
class="menu__link mobile-menu__link"
|
|
87
|
+
href={subsub.link}
|
|
88
|
+
>
|
|
89
|
+
{subsub.text}
|
|
90
|
+
</a>
|
|
91
|
+
</li>
|
|
92
|
+
))}
|
|
93
|
+
</ol>
|
|
94
|
+
</details>
|
|
95
|
+
) : (
|
|
96
|
+
<a class="menu__link mobile-menu__link" href={sub.link}>
|
|
97
|
+
{sub.text}
|
|
98
|
+
</a>
|
|
99
|
+
)}
|
|
100
|
+
</li>
|
|
101
|
+
))}
|
|
102
|
+
</ol>
|
|
103
|
+
</details>
|
|
104
|
+
) : (
|
|
105
|
+
<a class="mobile-menu__link" href={item.link}>
|
|
106
|
+
{item.text}
|
|
107
|
+
</a>
|
|
108
|
+
)}
|
|
109
|
+
</li>
|
|
110
|
+
))
|
|
111
|
+
}
|
|
94
112
|
</ol>
|
|
95
113
|
</nav>
|
|
96
114
|
|
|
@@ -131,7 +149,8 @@ const pagePathname = Astro.url.pathname;
|
|
|
131
149
|
}
|
|
132
150
|
|
|
133
151
|
.mobile-menu li a {
|
|
134
|
-
border: solid 1px
|
|
152
|
+
border: solid 1px
|
|
153
|
+
color-mix(in srgb, var(--mobile-accent-color) 20%, transparent);
|
|
135
154
|
border-radius: 4px;
|
|
136
155
|
width: 100%;
|
|
137
156
|
height: 4rem;
|
|
@@ -149,7 +168,11 @@ const pagePathname = Astro.url.pathname;
|
|
|
149
168
|
}
|
|
150
169
|
|
|
151
170
|
.mobile-details summary {
|
|
152
|
-
background: linear-gradient(
|
|
171
|
+
background: linear-gradient(
|
|
172
|
+
to right,
|
|
173
|
+
color-mix(in srgb, var(--mobile-accent-color) 20%, transparent),
|
|
174
|
+
transparent
|
|
175
|
+
);
|
|
153
176
|
border-radius: 4px;
|
|
154
177
|
width: 100%;
|
|
155
178
|
height: 4rem;
|
|
@@ -188,6 +211,9 @@ const pagePathname = Astro.url.pathname;
|
|
|
188
211
|
margin-left: 1rem;
|
|
189
212
|
margin-top: 1rem;
|
|
190
213
|
list-style: none;
|
|
214
|
+
gap: 1rem;
|
|
215
|
+
display: flex;
|
|
216
|
+
flex-direction: column;
|
|
191
217
|
}
|
|
192
218
|
|
|
193
219
|
.mobile-header__menu.is-active {
|
package/src/hamburger.ts
CHANGED
|
@@ -56,12 +56,26 @@ export class HamburgerButtonController {
|
|
|
56
56
|
document.addEventListener("click", (e: Event) => {
|
|
57
57
|
const target = e.target as Element;
|
|
58
58
|
|
|
59
|
-
// Check if the clicked element is
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
59
|
+
// Check if the clicked element is within the mobile menu
|
|
60
|
+
const mobileMenu = document.getElementById("mobile-header-menu");
|
|
61
|
+
if (!mobileMenu || !mobileMenu.contains(target)) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Check if the clicked element is a menu link (including all mobile menu variants)
|
|
66
|
+
const isMenuLink = target?.matches?.(".mobile-menu__link") ||
|
|
67
|
+
target?.matches?.(".menu__link.mobile-menu__link") ||
|
|
68
|
+
target?.closest?.(".mobile-menu__link") ||
|
|
69
|
+
target?.closest?.(".menu__link.mobile-menu__link");
|
|
70
|
+
|
|
71
|
+
if (isMenuLink) {
|
|
72
|
+
// Only close if it's an actual link with a valid href (not a summary/dropdown toggle)
|
|
73
|
+
const closestLink = target.closest("a");
|
|
74
|
+
if (closestLink && closestLink.href &&
|
|
75
|
+
closestLink.href !== "#" &&
|
|
76
|
+
!closestLink.href.endsWith("#")) {
|
|
77
|
+
this.closeMenu();
|
|
78
|
+
}
|
|
65
79
|
}
|
|
66
80
|
});
|
|
67
81
|
}
|