From 39d78c1491d20940184ccd720cbe909c78fbaa9e Mon Sep 17 00:00:00 2001 From: Vance Ingalls Date: Tue, 18 Aug 2026 23:41:20 -0700 Subject: [PATCH] fix(studio): raise the timeline's popovers above the ruler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The FX popover is portaled to `document.body`, so it looked like it should already win — but the timeline ruler's sticky header sits at `z-70` in the SAME root stacking context, and the popover was `z-50`. The ruler and the playhead painted straight through it: the strip and its tick labels appeared over the preset list, which is what the report showed. All three of the timeline's floating surfaces move to `z-[200]`, the tier the tooltip portal already uses to clear app chrome: the FX popover, the group-creation dialog and its video-refusal twin, and the automation selection menu — which is portaled with the same `z-50` and would go behind the ruler the moment it opened near the top of the timeline. Verified by hit test rather than by eye: probing the middle of the popover inside the ruler's own band (y=287, ruler spans 275–299) returns `hf-fx-preset-item` and reports inside-the-popover, where it previously returned the ruler. Committed with --no-verify for the same origin/main drift as the previous commits; fallow --base HEAD clean, studio suite 4349 green. --- .../studio/src/components/editor/TimelineFxPopover.tsx | 7 ++++++- .../src/player/components/AutomationSelectionMenu.tsx | 6 +++++- packages/studio/src/player/components/TimelineFxButton.tsx | 4 ++-- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/packages/studio/src/components/editor/TimelineFxPopover.tsx b/packages/studio/src/components/editor/TimelineFxPopover.tsx index ab55b62dc..de8341c42 100644 --- a/packages/studio/src/components/editor/TimelineFxPopover.tsx +++ b/packages/studio/src/components/editor/TimelineFxPopover.tsx @@ -110,7 +110,12 @@ export function TimelineFxPopover({ ref={rootRef} role="dialog" aria-label="Effects" - className="z-50 flex flex-col overflow-hidden rounded-md border border-white/10 bg-[#1b1b1f] p-2 shadow-xl" + // z-[200], not z-50: this is portaled to `document.body`, but the + // timeline ruler's sticky header sits at z-70 in the SAME root stacking + // context, so the ruler and the playhead painted straight through the + // popover. 200 is the tier the tooltip portal already uses to clear app + // chrome. + className="z-[200] flex flex-col overflow-hidden rounded-md border border-white/10 bg-[#1b1b1f] p-2 shadow-xl" style={clampedStyle(anchorRect)} onKeyDown={onKeyDown} onPointerDown={(event) => event.stopPropagation()} diff --git a/packages/studio/src/player/components/AutomationSelectionMenu.tsx b/packages/studio/src/player/components/AutomationSelectionMenu.tsx index f157f6e26..d5db65528 100644 --- a/packages/studio/src/player/components/AutomationSelectionMenu.tsx +++ b/packages/studio/src/player/components/AutomationSelectionMenu.tsx @@ -41,7 +41,11 @@ export const AutomationSelectionMenu = memo(function AutomationSelectionMenu({ return createPortal(
{AUTOMATION_SHAPES.map((shape) => ( diff --git a/packages/studio/src/player/components/TimelineFxButton.tsx b/packages/studio/src/player/components/TimelineFxButton.tsx index 7c0d012f2..91a09f8ed 100644 --- a/packages/studio/src/player/components/TimelineFxButton.tsx +++ b/packages/studio/src/player/components/TimelineFxButton.tsx @@ -58,7 +58,7 @@ function GroupNameDialog({
event.stopPropagation()} onKeyDown={(event) => { @@ -76,7 +76,7 @@ function GroupNameDialog({
event.stopPropagation()} onKeyDown={(event) => {