diff --git a/scripts/e2e/run-playwright-smoke.js b/scripts/e2e/run-playwright-smoke.js index 9776e48f..e263dc71 100644 --- a/scripts/e2e/run-playwright-smoke.js +++ b/scripts/e2e/run-playwright-smoke.js @@ -529,6 +529,10 @@ async function assertMobileNavigationKeyboardPath(browser, baseUrl) { const menuTrigger = page.getByRole("button", { name: /Open Navigation/i }).first(); await menuTrigger.waitFor({ state: "visible", timeout: 15_000 }); + await page.waitForFunction(() => { + const buttons = Array.from(document.querySelectorAll("button")); + return buttons.some((button) => /Open Navigation/i.test(button.textContent || button.getAttribute("aria-label") || "") && !button.disabled); + }, null, { timeout: 15_000 }); await menuTrigger.focus(); await page.keyboard.press("Enter"); diff --git a/src/components/layout/deferred-mobile-nav-menu.tsx b/src/components/layout/deferred-mobile-nav-menu.tsx index b382cd73..eadd3cae 100644 --- a/src/components/layout/deferred-mobile-nav-menu.tsx +++ b/src/components/layout/deferred-mobile-nav-menu.tsx @@ -2,6 +2,7 @@ import * as React from "react" import dynamic from "next/dynamic" +import { useHasMounted } from "@/hooks/use-has-mounted" const NavbarMobileMenu = dynamic( () => import("./navbar-mobile-menu").then((mod) => mod.NavbarMobileMenu), @@ -12,6 +13,7 @@ export function DeferredMobileNavMenu({ }: { menuLabel: string }) { + const hasMounted = useHasMounted() const [isMounted, setIsMounted] = React.useState(false) const [isOpen, setIsOpen] = React.useState(false) const triggerRef = React.useRef(null) @@ -24,11 +26,13 @@ export function DeferredMobileNavMenu({ }, []) const mountMenu = React.useCallback(() => { + if (!hasMounted) return + React.startTransition(() => { setIsMounted(true) }) setIsOpen(true) - }, []) + }, [hasMounted]) return ( <> @@ -38,6 +42,7 @@ export function DeferredMobileNavMenu({ className="inline-flex h-11 w-11 items-center justify-center rounded-lg text-sm font-medium transition-[color,background-color,border-color,box-shadow,opacity,transform] outline-none hover:bg-accent hover:text-accent-foreground focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 lg:hidden dark:hover:bg-accent/50" onClick={isMounted ? () => setIsOpen(true) : mountMenu} aria-expanded={isMounted ? isOpen : undefined} + disabled={!hasMounted} >