[fix](trx-frontend-http): lift the header menus out of the header #28

Merged
sjg merged 1 commits from fix/menus-above-spectrum into main 2026-08-02 23:31:19 +02:00
Owner

Why the previous fix wasn't enough

Fixed positioning escaped the clipping, but not the stacking.

.tab-bar carries z-index: 2, which makes it a stacking context — so any z-index a descendant carries is confined below level 2, no matter how large. The spectrum overlays paint as high as 9600, so both dropdowns opened underneath them. Raising the menu's own z-index cannot fix this; the number is meaningless outside its context.

The fix

Reparent each menu to document.body when it opens. Leaving that subtree is the only way out of an ancestor's stacking context. The menus are already positioned in viewport coordinates, so nothing else about them changes.

The outside-click test now considers the menu as well as its wrapper, since the two are no longer nested — without that, clicking an item would dismiss the menu before the click registered.

Verified by hit testing

Not by inspecting z-index, which is what made the previous attempt look correct:

parent: BODY   zIndex: 9700   rect: 206×193
elementFromPoint(menu centre) -> mobile-more-menu   insideMenu: true

The menu is the topmost painted element at its own centre. Screenshot confirms it drawing over the spectrum panel.

Full gate green — typecheck, lint, 34/34 test, build, test:browser.

🤖 Generated with Claude Code

https://claude.ai/code/session_01GdyUjuXejCEfiub675z6cz

## Why the previous fix wasn't enough Fixed positioning escaped the *clipping*, but not the *stacking*. `.tab-bar` carries `z-index: 2`, which makes it a stacking context — so any z-index a descendant carries is confined below level 2, no matter how large. The spectrum overlays paint as high as **9600**, so both dropdowns opened underneath them. Raising the menu's own z-index cannot fix this; the number is meaningless outside its context. ## The fix Reparent each menu to `document.body` when it opens. Leaving that subtree is the only way out of an ancestor's stacking context. The menus are already positioned in viewport coordinates, so nothing else about them changes. The outside-click test now considers the menu as well as its wrapper, since the two are no longer nested — without that, clicking an item would dismiss the menu before the click registered. ## Verified by hit testing Not by inspecting z-index, which is what made the previous attempt look correct: ``` parent: BODY zIndex: 9700 rect: 206×193 elementFromPoint(menu centre) -> mobile-more-menu insideMenu: true ``` The menu is the topmost painted element at its own centre. Screenshot confirms it drawing over the spectrum panel. Full gate green — `typecheck`, `lint`, 34/34 `test`, `build`, `test:browser`. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01GdyUjuXejCEfiub675z6cz
sjg added 1 commit 2026-08-02 23:28:59 +02:00
[fix](trx-frontend-http): lift the header menus out of the header
CI / lint (pull_request) Successful in 2m24s
CI / test (pull_request) Successful in 8m21s
CI / frontend (pull_request) Successful in 3m5s
CI / reuse (pull_request) Successful in 3s
CI / lint (push) Successful in 2m17s
CI / test (push) Successful in 7m36s
CI / frontend (push) Successful in 2m9s
CI / reuse (push) Successful in 3s
b06c37affa
Fixed positioning escaped the clipping, but not the stacking: the header
carries `z-index: 2`, which makes it a stacking context, so whatever
z-index a menu inside it carries is confined below level 2.  The spectrum
overlays paint as high as 9600, so both dropdowns opened underneath them.

Reparent each menu to the body when it opens.  Leaving that subtree is
the only way out of an ancestor's stacking context, and the menus are
already positioned in viewport coordinates, so nothing else about them
changes.  The outside-click test now considers the menu as well as its
wrapper, since the two are no longer nested.

Verified by hit testing rather than by inspecting z-index:
elementFromPoint at the open menu's centre returns the menu.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GdyUjuXejCEfiub675z6cz
Signed-off-by: Stan Grams <sjg@haxx.space>
sjg merged commit b06c37affa into main 2026-08-02 23:31:19 +02:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sjg/trx-rs#28