@sofidevo/astro-dynamic-header 1.0.28 → 1.0.30
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/README.md +163 -24
- package/package.json +11 -5
- package/src/Header.astro +5 -4
- package/src/MobileNav.astro +2 -1
- package/src/NavMenu.astro +7 -8
package/README.md
CHANGED
|
@@ -7,7 +7,8 @@ A dynamic, responsive header component for Astro projects that can switch betwee
|
|
|
7
7
|
- 🎨 **Dynamic Styles**: Switch between floating and fullscreen header layouts
|
|
8
8
|
- 📱 **Fully Responsive**: Mobile-first design with hamburger menu
|
|
9
9
|
- 🎯 **Multi-level Dropdowns**: Support for nested navigation menus
|
|
10
|
-
-
|
|
10
|
+
- � **Slot Support**: Customizable slots for desktop header and mobile panel content
|
|
11
|
+
- �🚀 **TypeScript Support**: Full type safety and IntelliSense
|
|
11
12
|
- 🎨 **Customizable**: Extensive customization options for colors, sizes, and behavior
|
|
12
13
|
- ⚡ **Astro Optimized**: Built specifically for Astro framework
|
|
13
14
|
|
|
@@ -132,6 +133,131 @@ interface MenuItemType {
|
|
|
132
133
|
}
|
|
133
134
|
```
|
|
134
135
|
|
|
136
|
+
## Slots Support
|
|
137
|
+
|
|
138
|
+
The Header component provides two customizable slots that allow you to add additional content:
|
|
139
|
+
|
|
140
|
+
### Available Slots
|
|
141
|
+
|
|
142
|
+
| Slot Name | Location | Visibility | Description |
|
|
143
|
+
|-----------|----------|------------|-------------|
|
|
144
|
+
| `slot-desktop` | Header (desktop & mobile) | Always visible | Add content to the main header area |
|
|
145
|
+
| `slot-panel` | Mobile navigation panel | Mobile only | Add content to the mobile menu panel |
|
|
146
|
+
|
|
147
|
+
### Slot Examples
|
|
148
|
+
|
|
149
|
+
#### Using Individual Slots
|
|
150
|
+
|
|
151
|
+
```astro
|
|
152
|
+
---
|
|
153
|
+
import Header from '@sofidevo/astro-dynamic-header/Header';
|
|
154
|
+
|
|
155
|
+
const menuItems = [
|
|
156
|
+
{ link: '/about', text: 'About' },
|
|
157
|
+
{ link: '/contact', text: 'Contact' },
|
|
158
|
+
];
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
<!-- Adding content only to desktop header -->
|
|
162
|
+
<Header
|
|
163
|
+
headerType="floating"
|
|
164
|
+
logoSrc="/logo.png"
|
|
165
|
+
menuItems={menuItems}
|
|
166
|
+
>
|
|
167
|
+
<button slot="slot-desktop" class="cta-button">Get Started</button>
|
|
168
|
+
</Header>
|
|
169
|
+
|
|
170
|
+
<!-- Adding content only to mobile panel -->
|
|
171
|
+
<Header
|
|
172
|
+
headerType="fullscreen"
|
|
173
|
+
logoSrc="/logo.png"
|
|
174
|
+
menuItems={menuItems}
|
|
175
|
+
>
|
|
176
|
+
<div slot="slot-panel" class="mobile-footer">
|
|
177
|
+
<p>© 2024 My Company</p>
|
|
178
|
+
<div class="social-links">
|
|
179
|
+
<a href="/twitter">Twitter</a>
|
|
180
|
+
<a href="/linkedin">LinkedIn</a>
|
|
181
|
+
</div>
|
|
182
|
+
</div>
|
|
183
|
+
</Header>
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
#### Using Both Slots Together
|
|
187
|
+
|
|
188
|
+
```astro
|
|
189
|
+
---
|
|
190
|
+
import Header from '@sofidevo/astro-dynamic-header/Header';
|
|
191
|
+
|
|
192
|
+
const menuItems = [
|
|
193
|
+
{ link: '/about', text: 'About' },
|
|
194
|
+
{ link: '/services', text: 'Services' },
|
|
195
|
+
{ link: '/contact', text: 'Contact' },
|
|
196
|
+
];
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
<Header
|
|
200
|
+
headerType="fullscreen"
|
|
201
|
+
logoSrc="/logo.png"
|
|
202
|
+
logoAlt="My Company"
|
|
203
|
+
logoWidth="150px"
|
|
204
|
+
homeUrl="/"
|
|
205
|
+
menuItems={menuItems}
|
|
206
|
+
backgroundColor="#000000dd"
|
|
207
|
+
backdropBlur="blur(15px)"
|
|
208
|
+
zIndex={100}
|
|
209
|
+
>
|
|
210
|
+
<!-- Content for desktop header -->
|
|
211
|
+
<button slot="slot-desktop" class="cta-button">
|
|
212
|
+
Sign Up
|
|
213
|
+
</button>
|
|
214
|
+
|
|
215
|
+
<!-- Content for mobile panel -->
|
|
216
|
+
<div slot="slot-panel" class="mobile-extras">
|
|
217
|
+
<button class="mobile-cta">Download App</button>
|
|
218
|
+
<div class="mobile-contact">
|
|
219
|
+
<p>Call us: +1 (555) 123-4567</p>
|
|
220
|
+
<p>Email: info@company.com</p>
|
|
221
|
+
</div>
|
|
222
|
+
</div>
|
|
223
|
+
</Header>
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
#### Responsive Slot Behavior
|
|
227
|
+
|
|
228
|
+
The `slot-desktop` is visible on both desktop and mobile by default. If you want to hide it on mobile, use CSS:
|
|
229
|
+
|
|
230
|
+
```css
|
|
231
|
+
/* Hide desktop slot on mobile devices */
|
|
232
|
+
@media (width < 768px) {
|
|
233
|
+
.cta-button {
|
|
234
|
+
display: none;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/* Or create responsive variants */
|
|
239
|
+
.desktop-only {
|
|
240
|
+
display: block;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
@media (width < 768px) {
|
|
244
|
+
.desktop-only {
|
|
245
|
+
display: none;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
```astro
|
|
251
|
+
<Header menuItems={menuItems}>
|
|
252
|
+
<button slot="slot-desktop" class="cta-button desktop-only">
|
|
253
|
+
Desktop CTA
|
|
254
|
+
</button>
|
|
255
|
+
<div slot="slot-panel">
|
|
256
|
+
<button class="mobile-cta">Mobile CTA</button>
|
|
257
|
+
</div>
|
|
258
|
+
</Header>
|
|
259
|
+
```
|
|
260
|
+
|
|
135
261
|
## Header Types
|
|
136
262
|
|
|
137
263
|
### Floating Header
|
|
@@ -146,27 +272,6 @@ interface MenuItemType {
|
|
|
146
272
|
- Edge-to-edge design
|
|
147
273
|
- Ideal for traditional website layouts
|
|
148
274
|
|
|
149
|
-
## Individual Components
|
|
150
|
-
|
|
151
|
-
You can also import and use components individually:
|
|
152
|
-
|
|
153
|
-
```astro
|
|
154
|
-
---
|
|
155
|
-
// Import individual components
|
|
156
|
-
import NavMenu from '@sofidevo/astro-dynamic-header/NavMenu';
|
|
157
|
-
import MobileNav from '@sofidevo/astro-dynamic-header/MobileNav';
|
|
158
|
-
import HamburgerButton from '@sofidevo/astro-dynamic-header/HamburgerButton';
|
|
159
|
-
|
|
160
|
-
// Or use the .astro extension explicitly
|
|
161
|
-
import NavMenu from '@sofidevo/astro-dynamic-header/NavMenu.astro';
|
|
162
|
-
import MobileNav from '@sofidevo/astro-dynamic-header/MobileNav.astro';
|
|
163
|
-
import HamburgerButton from '@sofidevo/astro-dynamic-header/HamburgerButton.astro';
|
|
164
|
-
---
|
|
165
|
-
|
|
166
|
-
<NavMenu menuItems={menuItems} showHomeLink={true} homeText="Home" />
|
|
167
|
-
<MobileNav menuItems={menuItems} accentColor="#00ffff" />
|
|
168
|
-
<HamburgerButton color="#ffffff" />
|
|
169
|
-
```
|
|
170
275
|
|
|
171
276
|
## Styling and Customization
|
|
172
277
|
|
|
@@ -242,9 +347,43 @@ If you encounter import errors, try these solutions:
|
|
|
242
347
|
|
|
243
348
|
Visit our demo website to see the component in action with interactive examples and complete documentation.
|
|
244
349
|
|
|
245
|
-
##
|
|
350
|
+
## Testing
|
|
351
|
+
|
|
352
|
+
This project includes a comprehensive test suite with 34 tests covering all critical functionality.
|
|
353
|
+
|
|
354
|
+
### Running Tests
|
|
355
|
+
|
|
356
|
+
```bash
|
|
357
|
+
# Run all tests
|
|
358
|
+
npm test
|
|
359
|
+
|
|
360
|
+
# Run tests in watch mode
|
|
361
|
+
npm run test:watch
|
|
362
|
+
|
|
363
|
+
# Run tests with coverage report
|
|
364
|
+
npm run test:coverage
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
### Test Coverage
|
|
368
|
+
|
|
369
|
+
The test suite covers:
|
|
370
|
+
|
|
371
|
+
#### Component Logic Tests
|
|
372
|
+
- **Header Component** (4 tests): Hamburger controller functionality, menu toggle behavior
|
|
373
|
+
- **HamburgerButton Component** (10 tests): Button states, responsive behavior, accessibility
|
|
374
|
+
- **MobileNav Component** (7 tests): Dropdown structure, nested submenus, conditional rendering
|
|
375
|
+
- **NavMenu Component** (6 tests): Dynamic positioning, submenu interactions, viewport adjustments
|
|
376
|
+
|
|
377
|
+
#### Integration Tests (7 tests)
|
|
378
|
+
- Component interaction flows
|
|
379
|
+
- Responsive behavior between mobile/desktop
|
|
380
|
+
- Keyboard navigation and accessibility
|
|
381
|
+
- Menu state management during navigation
|
|
246
382
|
|
|
247
|
-
|
|
383
|
+
### Test Technologies
|
|
384
|
+
- **Vitest**: Fast testing framework
|
|
385
|
+
- **jsdom**: DOM simulation for component testing
|
|
386
|
+
- **TypeScript**: Type-safe test writing
|
|
248
387
|
|
|
249
388
|
## License
|
|
250
389
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sofidevo/astro-dynamic-header",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.30",
|
|
4
4
|
"description": "A dynamic Astro header component that switches between floating and fullscreen styles",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.ts",
|
|
@@ -27,7 +27,10 @@
|
|
|
27
27
|
"build": "astro build",
|
|
28
28
|
"dev": "astro dev",
|
|
29
29
|
"check": "astro check",
|
|
30
|
-
"check:watch": "astro check --watch"
|
|
30
|
+
"check:watch": "astro check --watch",
|
|
31
|
+
"test": "vitest run",
|
|
32
|
+
"test:watch": "vitest",
|
|
33
|
+
"test:coverage": "vitest run --coverage"
|
|
31
34
|
},
|
|
32
35
|
"keywords": [
|
|
33
36
|
"astro",
|
|
@@ -50,8 +53,12 @@
|
|
|
50
53
|
},
|
|
51
54
|
"devDependencies": {
|
|
52
55
|
"@astrojs/check": "^0.9.0",
|
|
56
|
+
"@types/jsdom": "^21.1.7",
|
|
57
|
+
"@vitest/coverage-v8": "^3.2.4",
|
|
53
58
|
"astro": "^5.12.8",
|
|
54
|
-
"
|
|
59
|
+
"jsdom": "^26.1.0",
|
|
60
|
+
"typescript": "^5.0.0",
|
|
61
|
+
"vitest": "^3.2.4"
|
|
55
62
|
},
|
|
56
63
|
"repository": {
|
|
57
64
|
"type": "git",
|
|
@@ -60,6 +67,5 @@
|
|
|
60
67
|
"bugs": {
|
|
61
68
|
"url": "https://github.com/SofiDevO/astro-dynamic-header/issues"
|
|
62
69
|
},
|
|
63
|
-
"homepage": "https://
|
|
64
|
-
"demo": "https://base-astro-psi.vercel.app/fullscreen-demo"
|
|
70
|
+
"homepage": "https://base-astro-psi.vercel.app/fullscreen-demo"
|
|
65
71
|
}
|
package/src/Header.astro
CHANGED
|
@@ -88,10 +88,11 @@ const {
|
|
|
88
88
|
<img class="header__logo" src={logoSrc} alt={logoAlt} style={`width: ${logoWidth};`} />
|
|
89
89
|
</a>
|
|
90
90
|
<NavMenu menuItems={menuItems} />
|
|
91
|
-
<slot/>
|
|
91
|
+
<slot name="slot-desktop" />
|
|
92
92
|
<HamburgerButton />
|
|
93
|
-
|
|
94
|
-
|
|
93
|
+
<MobileNav menuItems={menuItems} type={headerType}>
|
|
94
|
+
<slot name="slot-panel" slot="slot-panel" />
|
|
95
|
+
</MobileNav>
|
|
95
96
|
|
|
96
97
|
</header>
|
|
97
98
|
</div>
|
|
@@ -114,7 +115,7 @@ const {
|
|
|
114
115
|
|
|
115
116
|
/* Floating header container styles */
|
|
116
117
|
.header__container--floating {
|
|
117
|
-
padding:
|
|
118
|
+
padding: 1rem;
|
|
118
119
|
}
|
|
119
120
|
|
|
120
121
|
/* Fullscreen header container styles */
|
package/src/MobileNav.astro
CHANGED
|
@@ -110,6 +110,7 @@ const pagePathname = Astro.url.pathname;
|
|
|
110
110
|
))
|
|
111
111
|
}
|
|
112
112
|
</ol>
|
|
113
|
+
<slot name="slot-panel" />
|
|
113
114
|
</nav>
|
|
114
115
|
|
|
115
116
|
<style>
|
|
@@ -122,7 +123,7 @@ const pagePathname = Astro.url.pathname;
|
|
|
122
123
|
width: 104vw;
|
|
123
124
|
height: 100dvh;
|
|
124
125
|
position: fixed;
|
|
125
|
-
top: -
|
|
126
|
+
top: -11px;
|
|
126
127
|
left: 0;
|
|
127
128
|
background: #151515;
|
|
128
129
|
z-index: 20;
|
package/src/NavMenu.astro
CHANGED
|
@@ -63,7 +63,7 @@ const pagePathname = Astro.url.pathname;
|
|
|
63
63
|
const rect = subsubmenu.getBoundingClientRect();
|
|
64
64
|
|
|
65
65
|
if (rect.right > viewportWidth) {
|
|
66
|
-
(subsubmenu as HTMLElement).style.left = "-
|
|
66
|
+
(subsubmenu as HTMLElement).style.left = "-210%";
|
|
67
67
|
(subsubmenu as HTMLElement).style.right = "auto";
|
|
68
68
|
const leftRect = subsubmenu.getBoundingClientRect();
|
|
69
69
|
|
|
@@ -190,7 +190,6 @@ const pagePathname = Astro.url.pathname;
|
|
|
190
190
|
}
|
|
191
191
|
|
|
192
192
|
.menu {
|
|
193
|
-
padding: 1rem;
|
|
194
193
|
list-style: none;
|
|
195
194
|
display: flex;
|
|
196
195
|
align-items: center;
|
|
@@ -203,7 +202,7 @@ const pagePathname = Astro.url.pathname;
|
|
|
203
202
|
|
|
204
203
|
.menu__link {
|
|
205
204
|
text-decoration: none;
|
|
206
|
-
padding: 0.5rem
|
|
205
|
+
padding: 0.5rem ;
|
|
207
206
|
display: flex;
|
|
208
207
|
align-items: center;
|
|
209
208
|
gap: 0.8rem;
|
|
@@ -214,7 +213,7 @@ const pagePathname = Astro.url.pathname;
|
|
|
214
213
|
@media screen and (min-width: 768px) {
|
|
215
214
|
.menu__link::after {
|
|
216
215
|
position: absolute;
|
|
217
|
-
top:
|
|
216
|
+
top: 33px;
|
|
218
217
|
left: 0;
|
|
219
218
|
content: "";
|
|
220
219
|
width: 100%;
|
|
@@ -265,7 +264,7 @@ const pagePathname = Astro.url.pathname;
|
|
|
265
264
|
justify-content: space-between;
|
|
266
265
|
align-items: center;
|
|
267
266
|
width: 100%;
|
|
268
|
-
height:
|
|
267
|
+
height: 1rem;
|
|
269
268
|
border-radius: 0.4rem;
|
|
270
269
|
color: #fff;
|
|
271
270
|
color: var(--color-tertiary, #fff);
|
|
@@ -278,7 +277,7 @@ const pagePathname = Astro.url.pathname;
|
|
|
278
277
|
|
|
279
278
|
.submenu__item--secondary a,
|
|
280
279
|
.submenu__item--tertiary a {
|
|
281
|
-
padding:
|
|
280
|
+
padding: 1rem;
|
|
282
281
|
}
|
|
283
282
|
|
|
284
283
|
.submenu__item--secondary a:hover,
|
|
@@ -288,7 +287,7 @@ const pagePathname = Astro.url.pathname;
|
|
|
288
287
|
}
|
|
289
288
|
|
|
290
289
|
.submenu {
|
|
291
|
-
padding:
|
|
290
|
+
padding: 0.9rem;
|
|
292
291
|
right: -23px;
|
|
293
292
|
}
|
|
294
293
|
|
|
@@ -337,7 +336,7 @@ const pagePathname = Astro.url.pathname;
|
|
|
337
336
|
.menu__item:hover > .submenu {
|
|
338
337
|
opacity: 1;
|
|
339
338
|
pointer-events: all;
|
|
340
|
-
transform: translateY(
|
|
339
|
+
transform: translateY(1.4rem);
|
|
341
340
|
}
|
|
342
341
|
|
|
343
342
|
.menu__item:hover > .submenu::after {
|