fix(player): portal the YouTube player modal out of the page scroller

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 <body>, 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.
This commit is contained in:
2026-07-17 21:43:37 +02:00
parent 9b4ee83ec8
commit 65ab33d632
+8 -2
View File
@@ -583,7 +583,12 @@ export default function PlayerModal({
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [active.id]);
return (
// Portaled to <body>, 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(
<div
ref={dialogRef}
className="fixed inset-0 z-50 flex items-center justify-center p-4 sm:p-6 bg-black/80 backdrop-blur-sm"
@@ -944,6 +949,7 @@ export default function PlayerModal({
</button>
)}
</div>
</div>
</div>,
document.body
);
}