Header Component
Header Component
Section titled “Header Component”The Header component provides a responsive navigation header with logo support, site branding, and a mobile-friendly menu.
Features
Section titled “Features”- ✅ 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
Basic Usage
Section titled “Basic Usage”---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)
Required Props
Section titled “Required Props”siteName
Section titled “siteName”Type: string
Required: Yes
The name of your podcast, displayed in the header.
<Header siteName="Strange Water" />Optional Props
Section titled “Optional Props”siteTagline
Section titled “siteTagline”Type: string
Default: undefined
A tagline displayed below the site name.
<Header siteName="Strange Water" siteTagline="Ethereum's podcast"/>logoUrl
Section titled “logoUrl”Type: string
Default: undefined
URL to your podcast logo. If not provided, auto-generates initials from siteName.
<Header siteName="My Podcast" logoUrl="/logo.png"/>navigation
Section titled “navigation”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}/>Complete Example
Section titled “Complete Example”---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}/>Responsive Behavior
Section titled “Responsive Behavior”Desktop (≥ 768px)
Section titled “Desktop (≥ 768px)”- Full horizontal navigation
- Logo and site name on left
- Navigation links on right
- Hover states on links
Mobile (< 768px)
Section titled “Mobile (< 768px)”- Hamburger menu button
- Collapsible mobile menu
- Stacked navigation links
- Touch-friendly targets
Styling
Section titled “Styling”Theme Variables
Section titled “Theme Variables”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 */Custom Styles
Section titled “Custom Styles”Override styles with CSS:
<Header siteName="My Podcast" />
<style> header { box-shadow: 0 2px 4px rgba(0,0,0,0.1); }</style>Tailwind Classes
Section titled “Tailwind Classes”The header uses Tailwind classes. Customize via tailwind.config.mjs:
theme: { extend: { colors: { 'header-bg': '#1a1a1a', 'header-text': '#ffffff', } }}Customization Examples
Section titled “Customization Examples”Example 1: Simple Custom Navigation
Section titled “Example 1: Simple Custom Navigation”<Header siteName="Dev Podcast" navigation={[ { href: '/', label: 'Home' }, { href: '/episodes', label: 'Listen' }, { href: '/sponsors', label: 'Sponsors' }, { href: '/contact', label: 'Contact' } ]}/>Example 2: Conditional Navigation
Section titled “Example 2: Conditional Navigation”---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' } ]}/>Example 3: With Logo and Tagline
Section titled “Example 3: With Logo and Tagline”<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' } ]}/>Override Component
Section titled “Override Component”Create your own header at src/components/Header.astro:
Minimal Override
Section titled “Minimal Override”---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>Extended Override
Section titled “Extended Override”---// Extend framework componentimport 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} />Accessibility
Section titled “Accessibility”The Header component follows WCAG 2.1 AA standards:
Semantic HTML
Section titled “Semantic HTML”<header> <nav> <a href="/">...</a> </nav></header>ARIA Labels
Section titled “ARIA Labels”<button id="mobile-menu-button" aria-label="Toggle mobile menu" aria-expanded="false"> Menu</button>Keyboard Navigation
Section titled “Keyboard Navigation”- Tab - Navigate through links
- Enter/Space - Activate link or toggle menu
- Escape - Close mobile menu (when open)
Screen Readers
Section titled “Screen Readers”- Navigation landmarks
- Descriptive link text
- Menu state announcements
Performance
Section titled “Performance”- Bundle Size: ~1 KB (including mobile menu script)
- JavaScript: Only for mobile menu toggle
- CSS: Inline with component
- Render: Static at build time
Mobile Menu
Section titled “Mobile Menu”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 iconsNo dependencies - Pure JavaScript, works everywhere.
Troubleshooting
Section titled “Troubleshooting”Logo not showing
Section titled “Logo not showing”Check the logo URL is accessible:
---const logoUrl = "/logo.png"; // Must exist in public/---
<Header logoUrl={logoUrl} />Navigation not rendering
Section titled “Navigation not rendering”Check navigation array structure:
---const navigation = [ { href: '/', label: 'Home' }, // ✅ Correct { url: '/', text: 'Home' }, // ❌ Wrong props];---Mobile menu not working
Section titled “Mobile menu not working”Ensure the <script> tag is included. If you override the component, copy the mobile menu script.
Theme colors not applying
Section titled “Theme colors not applying”Check theme is passed to component:
---const podcast = await getPodcast();---
<Header siteName={podcast?.name} theme={podcast?.theme} // ✅ Pass theme/>Related Components
Section titled “Related Components”- Footer - Companion footer component
Next Steps
Section titled “Next Steps”- Footer Component - Add a footer
- Component Overrides - Customize the header
- Theming - Customize colors and fonts