fix(nav): header menu popover renders off-screen on 404 pages#423
Merged
Conversation
…n 404 pages The popover's right offset was computed by an x-bind:style binding that evaluates during Alpine init, while <body x-cloak> is still display:none (x-cloak removal is deferred to a microtask). Every measured rect reads 0, yielding right: <viewport - 6>px, and since the binding's only reactive dependency is `width`, it never re-evaluated on static pages like the 404 page — leaving the menu entirely off-screen. Compute both top and right in the existing open-time updater instead, where layout is measurable, and reposition on scroll/resize while open. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… Course" Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Opening the hamburger menu in the navigation header on a 404 page (any missing URL) at desktop widths shows nothing — the popover renders completely off-screen to the left.
Root cause
The popover's horizontal position came from an
x-bind:stylebinding on the popover element that measured$refs.menuButton.getBoundingClientRect().rightto compute aright:offset.That binding evaluates synchronously during Alpine's init walk, but
<body>carriesx-cloak— and Alpine removesx-cloakin a deferred microtask after init completes. So the measurement runs while the entire page isdisplay: none: every rect reads 0 and the popover getsright: <viewportWidth - 6>px(measured: left edge at −442px on a 1440px viewport).The binding's only reactive dependency was
width(body width viax-resize), so it never re-evaluated until something changed the body's width. Content-heavy pages tend to get such a nudge after load (e.g. a layout-affecting scrollbar appearing) and silently self-heal; the short, static 404 page never does — which is why the bug reproduced reliably there. The verticaltopwas unaffected because it was already set in an open-time handler.Fix
x-bind:stylebinding.topandrightin the existing open-time updater (updatePopoverTop→updatePopoverPosition), which runs on the popovertoggleevent — by then layout is real and measurable. Belowlgit clears the inlinerightso the CSS mobile insets apply.resizeas well asscrollwhile open (listeners added on open, removed on close), so the popover stays anchored, including when resizing across thelgbreakpoint while open.Verification
Driven in headless Chrome (Playwright) against the local Herd site at 1440×900:
right: 1434px→ left edge at −442px (off-screen)top: 125px; right: 84px— anchored under the buttonrightat inittoponly; CSS insets position the sheetrightcleared, mobile insets take overTests: new
NavigationMobileMenuPopoverPositionTestexercises a real 404 URL and locks in open-time positioning + the scroll/resize listener pairing. It and the existingNavigationMobileMenuBreakpointTestpass (4 tests, 15 assertions). Pint passes.🤖 Generated with Claude Code