diff --git a/astro.config.mjs b/astro.config.mjs index 9e701b1d..85e0db8d 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -32,6 +32,7 @@ export default defineConfig({ Sidebar: './src/components/docs/Sidebar.astro', ThemeProvider: './src/components/docs/ThemeProvider.astro', ThemeSelect: './src/components/docs/EmptyComponent.astro', + MobileMenuToggle: './src/components/docs/EmptyComponent.astro', }, sidebar: [ { diff --git a/src/components/docs/Header.astro b/src/components/docs/Header.astro index 3dee7ac0..ebeed758 100644 --- a/src/components/docs/Header.astro +++ b/src/components/docs/Header.astro @@ -25,14 +25,14 @@ import SiteHeader from '../Header.astro'; padding: 0 !important; border-bottom: none !important; } - /* Visually hide Starlight's default circular menu button; header hamburger controls it */ - starlight-menu-button { - position: absolute !important; - opacity: 0 !important; - pointer-events: none !important; - width: 0 !important; - height: 0 !important; - overflow: hidden !important; + /* Prevent body scrolling when Starlight sidebar popover is open on mobile */ + body:has(.sidebar-pane:popover-open) { + overflow: hidden; + } + @media (min-width: 50rem) { + body:has(.sidebar-pane:popover-open) { + overflow: auto; + } } @@ -60,6 +60,7 @@ import SiteHeader from '../Header.astro'; const hamburger = document.querySelector('.ha-docs-header .hamburger'); const mobileNav = document.querySelector('.ha-docs-header nav#mobile'); const desktopNav = document.querySelector('.ha-docs-header nav#desktop'); + const sidebar = document.getElementById('starlight__sidebar'); // Populate mobile nav with desktop links if empty if (mobileNav && desktopNav && !mobileNav.hasChildNodes()) { @@ -72,12 +73,10 @@ import SiteHeader from '../Header.astro'; if (hamburger && !hamburger.hasAttribute('data-initialized')) { hamburger.setAttribute('data-initialized', 'true'); hamburger.addEventListener('click', () => { - const starlightBtn = document.querySelector('starlight-menu-button button') as HTMLButtonElement | null; - if (starlightBtn) { - // On pages with Starlight sidebar drawer, delegate toggle to Starlight - starlightBtn.click(); - const expanded = starlightBtn.getAttribute('aria-expanded'); - hamburger.setAttribute('aria-expanded', expanded || 'false'); + if (sidebar && typeof (sidebar as any).togglePopover === 'function') { + // On pages with Starlight sidebar drawer, toggle the sidebar popover + (sidebar as any).togglePopover(); + hamburger.setAttribute('aria-expanded', String(sidebar.matches(':popover-open'))); } else if (mobileNav) { // On splash pages without sidebar drawer, toggle nav#mobile const isExpanded = mobileNav.classList.toggle('active'); @@ -85,6 +84,18 @@ import SiteHeader from '../Header.astro'; } }); } + + // Keep hamburger aria-expanded synchronized with sidebar popover toggle events + if (sidebar && !sidebar.hasAttribute('data-toggle-listener')) { + sidebar.setAttribute('data-toggle-listener', 'true'); + sidebar.addEventListener('toggle', ((e: Event) => { + const customEvent = e as CustomEvent & { newState?: string }; + const isOpen = customEvent.newState ? customEvent.newState === 'open' : sidebar.matches(':popover-open'); + if (hamburger) { + hamburger.setAttribute('aria-expanded', String(isOpen)); + } + }) as EventListener); + } } // Close mobile nav when clicking outside @@ -111,17 +122,6 @@ import SiteHeader from '../Header.astro'; } }); - // Keep hamburger aria-expanded synchronized if Starlight's menu changes - const observer = new MutationObserver(() => { - const isExpanded = document.body.hasAttribute('data-mobile-menu-expanded'); - const hamburger = document.querySelector('.ha-docs-header .hamburger'); - const starlightBtn = document.querySelector('starlight-menu-button button'); - if (hamburger && starlightBtn) { - hamburger.setAttribute('aria-expanded', String(isExpanded)); - } - }); - observer.observe(document.body, { attributes: true, attributeFilter: ['data-mobile-menu-expanded'] }); - setupDocsMobileMenu(); document.addEventListener('astro:page-load', setupDocsMobileMenu);