Package Exports
- @sofidevo/astro-dynamic-header
- @sofidevo/astro-dynamic-header/HamburgerButton
- @sofidevo/astro-dynamic-header/HamburgerButton.astro
- @sofidevo/astro-dynamic-header/Header
- @sofidevo/astro-dynamic-header/Header.astro
- @sofidevo/astro-dynamic-header/MobileNav
- @sofidevo/astro-dynamic-header/MobileNav.astro
- @sofidevo/astro-dynamic-header/NavMenu
- @sofidevo/astro-dynamic-header/NavMenu.astro
Readme
@sofidevo/astro-dynamic-header
A dynamic, responsive header component for Astro projects that can switch between floating and fullscreen styles with multi-level dropdown navigation support.
Features
- Dynamic Styles: Switch between floating and fullscreen header layouts
- Fully Responsive: Mobile-first design with hamburger menu
- Multi-level Dropdowns: Support for nested navigation menus
- Slot Support: Customizable slots for desktop header and mobile panel content
- TypeScript Support: Full type safety and IntelliSense
- Customizable: Extensive customization options for colors, sizes, and behavior
- Astro Optimized: Built specifically for Astro framework
Live demo
https://base-astro-psi.vercel.app/fullscreen-demo
Installation
npm i @sofidevo/astro-dynamic-headerRequired Dependencies
You need to add the Iconify CDN to the head of your project for the hamburger menu icons to work properly:
<script src="https://code.iconify.design/iconify-icon/3.0.0/iconify-icon.min.js"></script>Add this to your main layout or in the <head> section of your Astro pages.
Quick Start
Basic Usage (Automatic Theme)
By default, the header uses preset="auto", which automatically detects the theme based on a .dark class on your root element (html or body).
---
import Header from '@sofidevo/astro-dynamic-header/Header';
const navigation = {
menuItems: [
{ link: '/about', text: 'About' },
]
};
---
<!-- Detects .dark class on root automatically -->
<Header navigation={navigation} />Advanced Usage (Dual-Theme Customization)
You can provide custom colors for both light and dark modes simultaneously.
---
import Header from '@sofidevo/astro-dynamic-header/Header';
const theme = {
light: {
accentColor: "#3e1c71",
backgroundColor: "rgba(255, 255, 255, 0.8)"
},
dark: {
accentColor: "#00ffff",
backgroundColor: "rgba(20, 20, 20, 0.9)"
}
};
---
<Header
preset="auto"
theme={theme}
navigation={navigation}
/>Component Props
Header Component
| Prop | Type | Default | Description |
|---|---|---|---|
headerType |
"floating" | "fullscreen" |
"floating" |
Header layout style |
preset |
"light" | "dark" | "auto" |
"auto" |
Theme behavior. auto follows root class. |
logo |
LogoConfig |
{} |
Logo configuration object |
navigation |
NavConfig |
{} |
Navigation configuration object |
theme |
DualThemeConfig |
{} |
Custom theme overrides for light/dark |
classNames |
CustomClassNames |
{} |
Custom class names for CSS Modules |
Config Objects
DualThemeConfig
| Propery | Type | Description |
|---|---|---|
light |
ThemeConfig |
Styles applied in light mode |
dark |
ThemeConfig |
Styles applied in dark mode |
ThemeConfig
| Propery | Type | Default |
|---|---|---|
backgroundColor |
string |
Preset default |
backgroundColorOpaque |
string |
Preset default |
backdropBlur |
string |
"blur(20px)" |
zIndex |
number |
10 |
textColor |
string |
Preset default |
accentColor |
string |
Preset default |
[!IMPORTANT] Transparency vs Solid Submenus: To ensure the best UI and avoid rendering bugs with
backdrop-filteron nested elements, submenus and the mobile navigation panel are solid/opaque.If you use a transparent
backgroundColor(e.g.,rgba), remember to also provide its solid counterpart inbackgroundColorOpaque.
<Header theme={{
light: {
backgroundColor: "rgba(255, 255, 255, 0.7)", // Transparent header body
backgroundColorOpaque: "#ffffff", // Solid submenus
}
}} />CustomClassNames
| Propery | Type | Description |
|---|---|---|
container |
string |
Main container class |
header |
string |
Header element class |
logo |
string |
Logo link container class |
logoText |
string |
Logo text class |
nav |
string |
Desktop navigation wrapper class |
Slots Support
The Header component provides a flexible slot system that allows you to add additional content:
Available Slots
| Slot Name | Location | Visibility | Description |
|---|---|---|---|
actions |
Header & Mobile panel | Responsive visibility | Add action buttons (login, signup, etc.) |
Example with Slots
---
import Header from '@sofidevo/astro-dynamic-header/Header';
const navigation = {
menuItems: [{ link: '/about', text: 'About' }]
};
---
<Header navigation={navigation}>
<div slot="actions">
<button class="login-btn">Login</button>
</div>
</Header>Styling Action Buttons
.header-actions {
display: flex;
gap: 0.5em;
align-items: center;
}
.btn {
padding: 0.5em 1em;
border: none;
border-radius: 6px;
cursor: pointer;
font-weight: 500;
text-decoration: none;
display: inline-flex;
align-items: center;
transition: all 0.2s ease;
}
.btn-outline {
background: transparent;
color: #ffffff;
border: 1px solid #ffffff;
}
.btn-outline:hover {
background: #ffffff;
color: #000000;
}
.btn-primary {
background: #00ffff;
color: #000000;
}
.btn-primary:hover {
background: #00cccc;
}Header Types
Floating Header
- Centered with max-width constraint
- Rounded corners
- Padding around container
- Perfect for modern, card-like designs
Fullscreen Header
- Full viewport width
- No border radius
- Edge-to-edge design
- Ideal for traditional website layouts
Styling and Customization
The component uses CSS custom properties that you can override:
:root {
--light-spot-color: #00ffff;
--color-tertiary: #ffffff;
--color-hamburger-lines: #ffffff;
}TypeScript Support
The package provides full TypeScript support. You can import types to ensure your configuration is correct:
---
import Header from '@sofidevo/astro-dynamic-header/Header';
import type {
NavConfig,
DualThemeConfig,
MenuItem,
SecondaryMenuItem
} from '@sofidevo/astro-dynamic-header';
const navigation: NavConfig = {
menuItems: [
{
link: '/products',
text: 'Products',
submenu: [
{ link: '/software', text: 'Software' },
{ link: '/hardware', text: 'Hardware' }
]
}
]
};
const theme: DualThemeConfig = {
light: {
accentColor: "#3e1c71",
backgroundColor: "rgba(255, 255, 255, 0.8)",
backgroundColorOpaque: "#ffffff"
},
dark: {
accentColor: "#00ffff",
backgroundColor: "rgba(10, 10, 10, 0.9)",
backgroundColorOpaque: "#0a0a0a"
}
};
---
<Header
navigation={navigation}
theme={theme}
preset="auto"
/>Available Types
| Type | Description |
|---|---|
MenuItem |
Top-level menu item with optional properties |
SecondaryMenuItem |
Second-level menu item |
TertiaryMenuItem |
Third-level menu item |
NavConfig |
Main navigation configuration object |
ThemeConfig |
Individual theme settings (colors, blur, etc.) |
DualThemeConfig |
Combined settings for light and dark modes |
LogoConfig |
Logo image and text configuration |
HeaderProps |
Main props for the Header component |
Browser Support
- All modern browsers (Chrome, Firefox, Safari, Edge)
- Mobile responsive design with optimized touch targets
- Supports CSS
backdrop-filterfor glassmorphism - Automatic theme switching based on OS or site preference via
.darkclass
Troubleshooting
Import Issues
If you encounter import errors, try these solutions:
Use direct subpath import:
import Header from '@sofidevo/astro-dynamic-header/Header';Check relative imports in TS: In some environments (like
node16), you might need to use the.jsextension even for TypeScript files when importing from the package internals, though the main entry point handles this for you.Verify TypeScript configuration:
// tsconfig.json { "compilerOptions": { "moduleResolution": "bundler", "allowImportingTsExtensions": true } }
Compatibility
- Astro 4.x and 5.x
- SSG Projects (Static Site Generation)
- SSR Projects (Server-Side Rendering)
- Hybrid Projects (output: 'hybrid')
Live Examples
Visit our demo website to see the component in action with interactive examples and complete documentation.
Testing
This project includes a comprehensive test suite with 34 tests covering all critical functionality.
Running Tests
# Run all tests
npm test
# Run tests in watch mode
npm run test:watch
# Run tests with coverage report
npm run test:coverageTest Coverage
The test suite covers:
Component Logic Tests
- Header Component (4 tests): Hamburger controller functionality, menu toggle behavior
- HamburgerButton Component (10 tests): Button states, responsive behavior, accessibility
- MobileNav Component (7 tests): Dropdown structure, nested submenus, conditional rendering
- NavMenu Component (6 tests): Dynamic positioning, submenu interactions, viewport adjustments
Integration Tests (7 tests)
- Component interaction flows
- Responsive behavior between mobile/desktop
- Keyboard navigation and accessibility
- Menu state management during navigation
Test Technologies
- Vitest: Fast testing framework
- jsdom: DOM simulation for component testing
- TypeScript: Type-safe test writing
License
MIT License - see the LICENSE file for details.
Support
If you find this package helpful, please consider giving it a star on GitHub!