fix(player): reclaim keyboard focus when fullscreen ends

UAT found a dead end: F -> YouTube's fullscreen button -> Esc left the player
maximised with no way back, and a further F produced a second, control-less
fullscreen with the wheel driving YouTube's own volume box.

Measured cause: reaching YouTube's control bar means clicking INTO the player,
which moves keyboard focus into the cross-origin iframe — and it stays there.
Our window-level shortcuts then never fire (document.activeElement === IFRAME),
so F went to YouTube instead of toggling our maximise.

Fix: on fullscreenchange, when fullscreen ends, focus the modal card again.

Verified in real Chrome, step by step:
- F -> maximised, no browser lock, focus on our card
- YouTube's own FS button -> real fullscreen (innerHeight 889 -> 1024)
- leaving fullscreen -> focus back on our card (was: still the iframe)
- F -> back to the normal modal view (was: a second fullscreen with no controls)
This commit is contained in:
2026-07-24 03:07:46 +02:00
parent 45654fc7ec
commit aae37591cb
+8 -3
View File
@@ -555,9 +555,8 @@ export default function PlayerModal({
return () => el.removeEventListener("wheel", onWheel);
}, []);
// Track whether the fullscreen element is ours — the player iframe (see fullscreenTarget) or,
// before the player exists, the stage. Covers F, our button, YouTube's own button and the
// browser's Esc exit alike, since all of them land on one of those two elements.
// Track the browser's fullscreen state. WE never request it any more (F maximises via CSS), so
// this is YouTube's own fullscreen — entered from its control bar, left by its button or Esc.
useEffect(() => {
const onChange = () => {
const fsEl = document.fullscreenElement;
@@ -567,6 +566,12 @@ export default function PlayerModal({
const ours = !!fsEl && (fsEl === stageRef.current || fsEl === frame);
isFullscreenRef.current = ours; // read by the once-bound keydown handler
setIsFullscreen(ours); // drives the overlay's pointer-events
// LEAVING fullscreen is where the user got stranded: to reach YouTube's fullscreen button
// they had to click INTO the player, which moves keyboard focus into the cross-origin iframe
// — and it stays there afterwards. Our window-level shortcuts then never fire (F went to
// YouTube instead, giving a second, control-less fullscreen), so the maximised view had no
// way out. Taking focus back here restores F/Space/arrows the moment fullscreen ends.
if (!fsEl) focusModal();
};
document.addEventListener("fullscreenchange", onChange);
return () => document.removeEventListener("fullscreenchange", onChange);