From 65ab33d632fff6cfd240f906909c39f26bb934c3 Mon Sep 17 00:00:00 2001 From: npeter83 Date: Fri, 17 Jul 2026 21:43:37 +0200 Subject: [PATCH] fix(player): portal the YouTube player modal out of the page scroller MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Same regression the S3 edge-fade caused for the Plex player, and the one my "swept the class" pass missed: PlayerModal is `fixed inset-0 z-50` but rendered inside the page scroller, so once that scroller got the mask it became a stacking context and scoped the modal's z-50 inside it — the nav rail (z-40) and header (z-30) painted over the player, and the fade dimmed its top edge (worst at browser zoom, where the centered card is smaller against the rail/panel). Portaled to , where every other full-screen overlay already lives. Verified: modal is body-parented, full-viewport, and hit-tests on top at the nav / filter / header / corner points with the main mask active. --- frontend/src/components/PlayerModal.tsx | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/PlayerModal.tsx b/frontend/src/components/PlayerModal.tsx index 8b08aa7..02dcf52 100644 --- a/frontend/src/components/PlayerModal.tsx +++ b/frontend/src/components/PlayerModal.tsx @@ -583,7 +583,12 @@ export default function PlayerModal({ // eslint-disable-next-line react-hooks/exhaustive-deps }, [active.id]); - return ( + // Portaled to , like every other full-screen overlay here. A fixed, full-viewport modal + // must not render inside the page scroller: once that scroller is a stacking context (its + // edge-fade mask makes it one) this z-50 is scoped inside it, and the nav rail (z-40) and the + // header (z-30) paint over the modal — worst at browser zoom, where the centered card is smaller + // relative to the rail/panel. (Same class as PlexPlayer; this one was the miss in that sweep.) + return createPortal(
)}
- + , + document.body ); }