Skip to content

fix(ui): lift portalled popups above app overlays - #611

Merged
crs48 merged 1 commit into
mainfrom
fix/popup-layer-zindex
Jul 21, 2026
Merged

fix(ui): lift portalled popups above app overlays#611
crs48 merged 1 commit into
mainfrom
fix/popup-layer-zindex

Conversation

@crs48

@crs48 crs48 commented Jul 21, 2026

Copy link
Copy Markdown
Owner

The bug

Opening a table column's ⋯ menu and trying to change its data type does nothing — the type dropdown renders behind the field popover, so its options can't be clicked.

Root cause

Base UI portals selects/menus/popovers/tooltips into <body>. The element that actually paints is the Positioner, and it had z-index: auto. The z-50 on the Popup inside it is scoped to the positioner's own stacking context and can't lift the subtree — so any app overlay with a real z-index wins.

The field menu is exactly that: a fixed inset-0 z-40 scrim. 40 > auto, so the scrim and its buttons paint over the open dropdown.

Verified in the running app — with the positioner at z-index: auto, a hit test at the centre of the open dropdown returns the popover's "Hide in view" button, not an option:

prefix_topElementAtPopupCentre:  BUTTON | w-full px-2 py-1 text-left text-sm rounded hover:bg-accent
postfix_topElementAtPopupCentre: DIV    | relative flex w-full cursor-default select-none items-center

The fix

Put the z-index on the positioner, via a shared POPUP_LAYER (packages/ui/src/primitives/layers.ts), applied to every portalled positioner: Select, Menu, Popover, Tooltip, ContextMenu. The value sits above the shell's whole overlay range (app overlays top out at z-[200], devtools at z-[10000]), so a dropdown opened from inside a scrim, modal, or devtools panel stays clickable.

This is systemic, not just the table view — a select inside a modal failed identically.

Verification

  • Ran the app (/app?demo=1 → CRM Accounts), opened the Stage column's ⋯ menu, and changed its type from Single select → Text end-to-end. Dropdown paints over the popover.
  • Regression test packages/ui/src/primitives/layers.test.tsx: the open dropdown's positioner carries POPUP_LAYER, and the layer sits above every shell overlay.
  • tsc --noEmit clean for @xnetjs/ui; primitive tests pass; prettier clean.

No changeset — @xnetjs/ui is private. Changelog fragment included.

🤖 Generated with Claude Code

Base UI portals selects, menus, popovers and tooltips into <body>, where
the Positioner — the element that actually paints — had `z-index: auto`.
The `z-50` on the Popup inside it is scoped to the positioner's own
stacking context and cannot lift the subtree, so any app overlay with a
real z-index painted over the popup.

That made the table view's column data-type selector unusable: the field
menu's `z-40` scrim covered the open dropdown, and a click aimed at an
option landed on the "Hide in view" button underneath it instead.

Put the z-index on the positioner via a shared POPUP_LAYER, above the
shell's overlay range (app overlays top out at z-[200], devtools at
z-[10000]), so a dropdown opened from inside any of them stays clickable.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: xNet Test <test@xnet.dev>
@crs48
crs48 temporarily deployed to pr-611 July 21, 2026 03:23 — with GitHub Actions Inactive
github-actions Bot added a commit that referenced this pull request Jul 21, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🖼️ UI changes in this PR

No visual differences detected in the changed UI.

CI run

github-actions Bot added a commit that referenced this pull request Jul 21, 2026
github-actions Bot added a commit that referenced this pull request Jul 21, 2026
@github-actions

github-actions Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Preview removed for PR #611.

@crs48
crs48 merged commit 4cd5604 into main Jul 21, 2026
15 checks passed
@crs48
crs48 deleted the fix/popup-layer-zindex branch July 21, 2026 03:32
github-actions Bot added a commit that referenced this pull request Jul 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant