Skip to content

Commit 4fa063d

Browse files
vanceingallsclaude
andcommitted
fix(studio): move the remaining body-portaled context menus to the same tier
The all-sites audit in review was right and the previous commit did half the set. Using `createPortal(…, document.body)` as the predicate rather than the timeline directory, four more surfaces sit in the root stacking context at `z-50` below the seven chrome tiers (60, 90, 91, 92, 94, 100, 110): - `player/components/ClipContextMenu.tsx:51` - `player/components/TrackGapContextMenu.tsx:78` - `player/components/KeyframeDiamondContextMenu.tsx:99` - `components/editor/CanvasContextMenu.tsx:215` The fourth is the easy one to miss — it is the only one outside `player/components/`, so a timeline-scoped sweep finds exactly the other three. It belongs to the same set by its own account: its className is byte-identical to `ClipContextMenu`'s and its header comment says it mirrors that file's look, positioning, and dismiss behaviour, portaled to `document.body`. Two body portals deliberately left alone. `sidebar/BlocksTab.tsx:125` portals `PromptPreviewModal`, which carries its own `z-[100]`/`z-[110]` modal tier — a `z-` class on the portal wrapper would be dead weight. `RenderQueue.tsx:235` is already `z-[200]`. `FileTree.tsx:336` and `FileTreeNodes.tsx:103` are `fixed z-50` but are NOT portaled — they render inside the sidebar's own stacking context, so the root-context argument does not reach them and raising them would be an unrelated change. Crossing the `z-[100]`/`z-[110]` modal backdrops is unreachable for the same reason it was for the first three: all four dismiss on an outside pointerdown, so the press that opens a modal closes the menu first. `CanvasContextMenu.test.tsx:95` asserted on `.fixed.z-50` to prove the menu did NOT render; left as-is it would have passed vacuously against any tier. Updated to the new class so it still fails if the menu renders. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent f904ebf commit 4fa063d

5 files changed

Lines changed: 5 additions & 5 deletions

File tree

packages/studio/src/components/editor/CanvasContextMenu.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ describe("CanvasContextMenu — handler gating", () => {
9292

9393
// No menu opened at all — no buttons, no dead-end items, no DOM mutation.
9494
expect(menuButtons()).toHaveLength(0);
95-
expect(document.body.querySelector(".fixed.z-50")).toBeNull();
95+
expect(document.body.querySelector(".fixed.z-\\[200\\]")).toBeNull();
9696
expect(el.style.zIndex).toBe("3");
9797
});
9898

packages/studio/src/components/editor/CanvasContextMenu.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ export const CanvasContextMenu = memo(function CanvasContextMenu({
212212
return createPortal(
213213
<div
214214
ref={menuRef}
215-
className="fixed z-50 bg-neutral-900 border border-neutral-700 rounded-md shadow-lg py-1 min-w-[180px]"
215+
className="fixed z-[200] bg-neutral-900 border border-neutral-700 rounded-md shadow-lg py-1 min-w-[180px]"
216216
style={{ left: adjustedX, top: adjustedY }}
217217
onPointerDown={stopBubble}
218218
onMouseDown={stopBubble}

packages/studio/src/player/components/ClipContextMenu.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ export const ClipContextMenu = memo(function ClipContextMenu({
4848
ref={menuRef}
4949
role="menu"
5050
aria-label="Clip actions"
51-
className="fixed z-50 bg-neutral-900 border border-neutral-700 rounded-md shadow-lg py-1 min-w-[180px]"
51+
className="fixed z-[200] bg-neutral-900 border border-neutral-700 rounded-md shadow-lg py-1 min-w-[180px]"
5252
style={{ left: adjustedX, top: adjustedY }}
5353
>
5454
{splitLabel && (

packages/studio/src/player/components/KeyframeDiamondContextMenu.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ export function KeyframeDiamondContextMenu({
9696
ref={menuRef}
9797
role="menu"
9898
aria-label="Keyframe actions"
99-
className="fixed z-50 bg-neutral-900 border border-neutral-700 rounded-md shadow-lg py-1 min-w-[180px] overflow-y-auto"
99+
className="fixed z-[200] bg-neutral-900 border border-neutral-700 rounded-md shadow-lg py-1 min-w-[180px] overflow-y-auto"
100100
style={{ left: adjustedX, top: adjustedY, maxHeight: `calc(100vh - ${adjustedY + 8}px)` }}
101101
>
102102
{onMoveToPlayhead && (

packages/studio/src/player/components/TrackGapContextMenu.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ export const TrackGapContextMenu = memo(function TrackGapContextMenu({
7575
return createPortal(
7676
<div
7777
ref={menuRef}
78-
className="fixed z-50 bg-neutral-900 border border-neutral-700 rounded-md shadow-lg py-1 min-w-[180px]"
78+
className="fixed z-[200] bg-neutral-900 border border-neutral-700 rounded-md shadow-lg py-1 min-w-[180px]"
7979
style={{ left: adjustedX, top: adjustedY }}
8080
onPointerLeave={() => onHoverAction(null)}
8181
>

0 commit comments

Comments
 (0)