Skip to content

ref(🥞): add Layer primitive with portal outlets and stacking context isolation#114516

Open
natemoo-re wants to merge 7 commits into
masterfrom
nm/zindex/layer-primitive
Open

ref(🥞): add Layer primitive with portal outlets and stacking context isolation#114516
natemoo-re wants to merge 7 commits into
masterfrom
nm/zindex/layer-primitive

Conversation

@natemoo-re
Copy link
Copy Markdown
Member

@natemoo-re natemoo-re commented Apr 30, 2026

Summary

Add a Layer component that uses isolation: isolate to create scoped stacking contexts. Each Layer provides a portal outlet for portaled children (tooltips, hovercards, dropdowns) so they remain contained within the Layer's paint order. Stacking order between sibling Layers is determined by DOM position, not z-index.

Layer Component

Three semantic variants (content, nav, overlay) describe the surface type. Recursive nesting is supported with automatic depth tracking. Each Layer renders a position: fixed; inset: 0; pointer-events: none portal outlet at the end of its DOM, following the same pattern already used by DrawerContainer.

Hooks

useLayerContext() returns the current { variant, depth, portalOutlet }. usePortalContainer() returns the nearest Layer's portal outlet element for use with createPortal.

This is purely additive with no consumers — safe to merge with zero behavioral change.

🥞 Layer Primitive Series

Test plan

  • Layer renders with isolation: isolate stacking context
  • Portal outlet renders as position: fixed; inset: 0; pointer-events: none
  • usePortalContainer() returns the nearest Layer's portal outlet
  • Nested Layers accumulate depth correctly
  • pnpm test-ci static/app/components/core/layer/

@natemoo-re natemoo-re requested a review from a team as a code owner April 30, 2026 23:35
@natemoo-re natemoo-re marked this pull request as draft April 30, 2026 23:35
@github-actions github-actions Bot added the Scope: Frontend Automatically applied to PRs that change frontend components label Apr 30, 2026
@natemoo-re natemoo-re changed the title ref(🥞): add Layer primitive ref(🥞): add Layer primitive with portal outlets and stacking context isolation Apr 30, 2026
@natemoo-re natemoo-re added the WIP label May 18, 2026
@natemoo-re natemoo-re force-pushed the nm/zindex/layer-primitive branch from d9e086a to 38c44e6 Compare May 20, 2026 21:05
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 20, 2026

📊 Type Coverage Diff

✅ No new type safety issues introduced. Coverage: 93.59%

Comment thread static/app/components/core/layer/layer.tsx
@natemoo-re natemoo-re force-pushed the nm/zindex/layer-primitive branch from 8c5a144 to 39b9752 Compare May 26, 2026 17:15
Comment thread static/app/components/core/layer/layer.tsx
natemoo-re and others added 5 commits May 28, 2026 11:16
Layer now supports a render child pattern for flex/grid contexts
where the wrapper div breaks layout. When children is a function,
Layer passes {className} and the consumer renders its own element.

Add z-index: 2147483647 to PortalOutlet so portaled content paints
above sticky headers and other positioned elements within the Layer.

Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
isolation: isolate alone creates a stacking context. position: relative
conflicts with consumer positioning (e.g. position: sticky) when using
the render child pattern.

Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
Each Layer now creates its own tooltip warmth group, so tooltips within
a stacking context share instant-open behavior while isolating warmth
from other Layers. Inner HoverOverlayGroupProviders can still override
for sub-groups.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Layer exports are unused until wire-portals lands consumers.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The previous inset: 0 approach created a full-viewport overlay that
Selenium's hit-testing saw as blocking clicks even with pointer-events:
none. Use width: 0; height: 0; overflow: visible instead — the outlet
has no bounding rect but portaled children still render via overflow.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Scope: Frontend Automatically applied to PRs that change frontend components WIP

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant