Skip to content

Header Component

The Header component provides a responsive navigation header with logo support, site branding, and a mobile-friendly menu.

  • ✅ Responsive design (mobile, tablet, desktop)
  • ✅ Mobile menu with hamburger toggle
  • ✅ Logo support (image or auto-generated initials)
  • ✅ Customizable navigation items
  • ✅ Theme-aware styling
  • ✅ Accessible (ARIA labels, keyboard navigation)
  • ✅ Zero-config defaults
---
import Header from '@rejected-media/podcast-framework-core/components/Header.astro';
---
<Header siteName="My Podcast" />

This creates a header with:

  • Site name “My Podcast”
  • Auto-generated logo (initials)
  • Default navigation (Home, Episodes, Guests, About)

Type: string Required: Yes

The name of your podcast, displayed in the header.

<Header siteName="Strange Water" />

Type: string Default: undefined

A tagline displayed below the site name.

<Header
siteName="Strange Water"
siteTagline="Ethereum's podcast"
/>

Type: string Default: undefined

URL to your podcast logo. If not provided, auto-generates initials from siteName.

<Header
siteName="My Podcast"
logoUrl="/logo.png"
/>

Type: NavigationItem[] Default: [Home, Episodes, Guests, About]

Array of navigation items.

NavigationItem Interface:

interface NavigationItem {
href: string;
label: string;
show?: boolean; // Optional conditional rendering
}

Example:

<Header
siteName="My Podcast"
navigation={[
{ href: '/', label: 'Home' },
{ href: '/episodes', label: 'Episodes' },
{ href: '/guests', label: 'Guests' },
{ href: '/about', label: 'About' },
{ href: '/contribute', label: 'Contribute', show: podcast?.isActive }
]}
/>

Type: Theme Default: defaultTheme

Theme object controlling colors, fonts, and layout.

---
import { getPodcast } from '@rejected-media/podcast-framework-core';
const podcast = await getPodcast();
---
<Header
siteName={podcast?.name}
theme={podcast?.theme}
/>
---
import Header from '@rejected-media/podcast-framework-core/components/Header.astro';
import { getPodcast } from '@rejected-media/podcast-framework-core';
const podcast = await getPodcast();
const navigation = [
{ href: '/', label: 'Home' },
{ href: '/episodes', label: 'Episodes' },
{ href: '/guests', label: 'Guests' },
{ href: '/about', label: 'About' },
{
href: '/contribute',
label: 'Contribute',
show: podcast?.isActive
}
];
---
<Header
siteName={podcast?.name || "My Podcast"}
siteTagline={podcast?.tagline}
logoUrl={podcast?.logo?.url}
navigation={navigation}
theme={podcast?.theme}
/>
  • Full horizontal navigation
  • Logo and site name on left
  • Navigation links on right
  • Hover states on links
  • Hamburger menu button
  • Collapsible mobile menu
  • Stacked navigation links
  • Touch-friendly targets

The Header uses CSS custom properties from your theme:

--color-header-bg /* Header background color */
--color-header-text /* Header text color */
--color-primary /* Logo/accent color */
--color-secondary /* Navigation link color */

Override styles with CSS:

<Header siteName="My Podcast" />
<style>
header {
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
</style>

The header uses Tailwind classes. Customize via tailwind.config.mjs:

theme: {
extend: {
colors: {
'header-bg': '#1a1a1a',
'header-text': '#ffffff',
}
}
}
<Header
siteName="Dev Podcast"
navigation={[
{ href: '/', label: 'Home' },
{ href: '/episodes', label: 'Listen' },
{ href: '/sponsors', label: 'Sponsors' },
{ href: '/contact', label: 'Contact' }
]}
/>
---
const podcast = await getPodcast();
const isActive = podcast?.isActive;
---
<Header
siteName={podcast?.name}
navigation={[
{ href: '/', label: 'Home' },
{ href: '/episodes', label: 'Episodes' },
{ href: '/contribute', label: 'Contribute', show: isActive },
{ href: '/about', label: 'About' }
]}
/>
<Header
siteName="Tech Talk"
siteTagline="Weekly conversations with innovators"
logoUrl="/images/logo.svg"
navigation={[
{ href: '/', label: 'Home' },
{ href: '/episodes', label: 'Episodes' },
{ href: '/blog', label: 'Blog' }
]}
/>

Create your own header at src/components/Header.astro:

---
export interface Props {
siteName: string;
}
const { siteName } = Astro.props;
---
<header class="bg-black text-white p-4">
<nav class="container mx-auto flex justify-between items-center">
<a href="/" class="text-2xl font-bold">{siteName}</a>
<div class="flex gap-6">
<a href="/episodes">Episodes</a>
<a href="/about">About</a>
</div>
</nav>
</header>
---
// Extend framework component
import FrameworkHeader from '@rejected-media/podcast-framework-core/components/Header.astro';
export interface Props {
siteName: string;
showBanner?: boolean;
}
const { showBanner, ...rest } = Astro.props;
---
{showBanner && (
<div class="bg-blue-500 text-white text-center py-2">
🎉 New episode every Monday!
</div>
)}
<FrameworkHeader {...rest} />

The Header component follows WCAG 2.1 AA standards:

<header>
<nav>
<a href="/">...</a>
</nav>
</header>
<button
id="mobile-menu-button"
aria-label="Toggle mobile menu"
aria-expanded="false"
>
Menu
</button>
  • Tab - Navigate through links
  • Enter/Space - Activate link or toggle menu
  • Escape - Close mobile menu (when open)
  • Navigation landmarks
  • Descriptive link text
  • Menu state announcements
  • Bundle Size: ~1 KB (including mobile menu script)
  • JavaScript: Only for mobile menu toggle
  • CSS: Inline with component
  • Render: Static at build time

The mobile menu uses vanilla JavaScript for toggle functionality:

// Toggles on button click
// Closes when link is clicked
// Updates ARIA states
// Shows/hides menu and icons

No dependencies - Pure JavaScript, works everywhere.

Check the logo URL is accessible:

---
const logoUrl = "/logo.png"; // Must exist in public/
---
<Header logoUrl={logoUrl} />

Check navigation array structure:

---
const navigation = [
{ href: '/', label: 'Home' }, // ✅ Correct
{ url: '/', text: 'Home' }, // ❌ Wrong props
];
---

Ensure the <script> tag is included. If you override the component, copy the mobile menu script.

Check theme is passed to component:

---
const podcast = await getPodcast();
---
<Header
siteName={podcast?.name}
theme={podcast?.theme} // ✅ Pass theme
/>
  • Footer - Companion footer component