Overlay / top-layer overhaul Phase 2: migrate all overlays, tokenize residuals, strict guard - #59
Merged
Merged
Conversation
…layer MentionDropdown, ReactionBar (hover tooltip -> manual popover, hover lifecycle preserved), ArtifactDetailHeader dropdowns, EmojiPicker, ProfileCard, NotificationPolicyMenu, ReadReceipt now open via <Popover>/use:topLayer (Popover API), dropping raw position:fixed/absolute + z-index. MessageInput passes the textarea as the MentionDropdown anchor. Each keeps its existing outside-click/keyboard dismiss handlers so jsdom unit coverage holds (the action capability-guards the native calls).
ReactionDetailsPanel, MemberContextMenu, and ChannelContextMenu (+ its submenu as a nested manual popover, design F.8) now use use:topLayer instead of portal()+hardcoded z-index (9999/250). Rewrite context-menu-top-layer-bugfix.spec.js: the old z-index:9999 + @Attach portal() source pins are gone, so it now asserts the new primitive usage (use:topLayer, no portal, no bare z-index; two use:topLayer for the menu+ submenu) plus render/outside-click/unmount behaviour. Adapt reaction-details-panel.spec.js off the portal-parent assertion.
LeaveChannelDialog, TypeNameConfirmDialog, InviteParticipantDialog, ChannelDirectoryModal, KeyboardShortcutsHelp, and ForwardPicker now render a native <dialog> driven by showModal() via use:topLayer (or the <Modal> wrapper), using the native ::backdrop + built-in focus-trap and inert background. Drops the manual portals, backdrop elements, position:fixed and z-index. Existing cancel/confirm handlers retained for jsdom coverage.
Extend the app.css token scale with value-preserving local rungs (--z-raised/content/elevated) + --z-noise, and collapse every remaining bare z-index onto var(--z-*): toasts (--z-toast), banners (--z-banner), docked panels (--z-panel), sidebar (--z-sidebar), in-flow content, and the App.svelte mobile-sidebar block. Migrate the App.svelte Ctrl+J quick-join prompt to a native <dialog use:topLayer> with a native ::backdrop, dropping its manual backdrop + z-index:9000. Toasts/banners stay non-top-layer by design (a top-layer toast would steal focus / inert the page).
Shrink the ALLOWED set to its irreducible core: the passive toasts/banners (must NOT be top layer, design F.5) and the three bits-ui components (ContextMenu/ChannelModal/ConfirmDialog, design F.1). Every other overlay/panel/in-flow file plus App.svelte and app.css now passes both rules on merit (uses the primitive, carries only var(--z-*) tokens). Update the comments + the self-doc test to assert the strict core.
Scenario 14 gains on-top + native-pseudo-class assertions for the new trap pairs: MentionDropdown over the message list (:popover-open), ChannelContextMenu over an open backdrop-filter panel (:popover-open), and the quick-join native :modal dialog (inert background + Esc dismiss), all via expectLocatorOnTop. Rewrite the 04/05 source-pins that asserted the removed z-index:9999 + @Attach portal() to assert use:topLayer instead, and update the ProfileCard dismiss test to a real outside-click (its backdrop element is gone).
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.
Overlay / top-layer overhaul — Phase 2
Builds on Phase 1 (#58: the
topLayeraction,<Modal>/<Popover>wrappers, the--z-*token scale, the Tier-1 guard, StatusEditor). Phase 2 migrates every remaining floating overlay off ad-hocposition:fixed/absolute+ manual z-index (and the partial portaling) onto the browser native top layer, tokenizes all residual surfaces, and flips the guard to strict.Anchored overlays →
<Popover>/use:topLayerMentionDropdown (anchored to the composer textarea), ReactionBar (hover tooltip → manual popover, hover lifecycle preserved), ArtifactDetailHeader dropdowns, EmojiPicker, ProfileCard, NotificationPolicyMenu, ReadReceipt. Dropped their raw positioning + z-index; kept each component's own outside-click/keyboard dismiss handlers so jsdom unit coverage holds (the action capability-guards the native calls).
Already-portaled → drop portal()+z-index, use the primitive
ReactionDetailsPanel (was z250), MemberContextMenu (was z9999), ChannelContextMenu + its submenu (the submenu is a nested
manualpopover, §F.8). Rewrotetests/context-menu-top-layer-bugfix.spec.js— it pinnedz-index:9999+{@attach portal()}by regex (now gone); it asserts the new primitive instead. Also updated the matching 04/05 e2e source-pins.Manual-portal + raw modals → native
<dialog>.showModal()LeaveChannelDialog, TypeNameConfirmDialog, InviteParticipantDialog, ChannelDirectoryModal, KeyboardShortcutsHelp, ForwardPicker, and the App.svelte quick-join dialog — native
::backdrop+ built-in focus-trap, no manual portals/z-index.bits-ui kept (ContextMenu, ChannelModal, ConfirmDialog)
Unchanged — they already portal to
<body>with their own focus-trap (§F.1).Tokenized residual surfaces
Toasts (
--z-toast), banners (--z-banner), docked panels (--z-panel), sidebar (--z-sidebar), in-flow content, and the App mobile-sidebar block — all bare z-index collapsed ontovar(--z-*)(added value-preserving local rungs--z-raised/content/elevated+--z-noise). Toasts/banners stay non-top-layer by design.Strict guard
ALLOWEDshrunk to the 4 passive toasts/banners + the 3 bits-ui components; everything else passes both rules on merit (uses the primitive, onlyvar(--z-*)tokens).Verification
pnpm --dir web test: 1333 passed, 0 failed, 0 skipped (run 3×, stable).pnpm --dir web build: green..svelte.:popover-openover the message list; ChannelContextMenu:popover-openover an open backdrop-filter panel; quick-join native:modal+ inert background), all green in real Chromium.No version bump.
🤖 Generated with Claude Code