Skip to content

fix: keep player-button tooltip inside the fullscreen element - #4298

Draft
Laaaaksh wants to merge 2 commits into
code-charity:masterfrom
Laaaaksh:fix/4294-tooltip-stacking
Draft

fix: keep player-button tooltip inside the fullscreen element#4298
Laaaaksh wants to merge 2 commits into
code-charity:masterfrom
Laaaaksh:fix/4294-tooltip-stacking

Conversation

@Laaaaksh

Copy link
Copy Markdown

Fixes #4294

Reproduction

On a real youtube.com/watch page with the extension's actual button/tooltip
code (ImprovedTube.createPlayerButton in
js&css/web-accessible/functions.js), hover a custom player button (e.g. the
playback speed button) while the player is in the browser's native
Fullscreen mode (the .html5-video-player element via the Fullscreen API,
same as YouTube's own fullscreen button uses).

  • In normal/theater mode the tooltip renders fine, above the video.
  • Once fullscreen is entered, the tooltip becomes completely invisible —
    document.elementFromPoint() at the tooltip's own coordinates returns the
    <video> element, not the tooltip, and a screenshot confirms no tooltip is
    painted anywhere near the button.

Root cause: the tooltip <div class="it-player-button--tooltip"> is always
appended to document.body. Per the Fullscreen API spec, once an element
(here .html5-video-player) is the document's fullscreenElement, only that
element's own subtree is painted — siblings/ancestors like document.body's
other children stop rendering. A position: fixed element outside the
fullscreen subtree therefore renders behind (i.e. not on top of) the video,
matching the reporter's screenshot and description ("tooltips are hidden
behind the video player").

Note: PR #4295 ("fix: show player tooltips above video") was merged into
master shortly before this branch and also targeted tooltip/video
layering, but issue #4294 remained open — its z-index change didn't address
this fullscreen-subtree stacking root cause, which is orthogonal to z-index.

What changed

In ImprovedTube.createPlayerButton's mouseover handler
(js&css/web-accessible/functions.js), the tooltip is now appended to the
current fullscreen element instead of always document.body:

const fullscreenRoot = document.fullscreenElement ||
	document.webkitFullscreenElement ||
	document.mozFullScreenElement ||
	document.body;

so it stays inside the rendered subtree whether or not the player is
fullscreen. The vendor-prefixed fallbacks match the same set the codebase
already checks elsewhere for fullscreen detection (player.js:458-463),
covering engines that only expose a prefixed API.

How it was tested

  • Live browser repro/verify (chrome-devtools-axi driving a real Chrome
    session against a live youtube.com/watch page, injecting the extension's
    actual createPlayerButton/tooltip code and CSS): confirmed the tooltip
    was invisible in fullscreen before the fix (screenshot + elementFromPoint
    check), and confirmed it renders visibly above the video in fullscreen
    after the fix, while remaining unchanged/visible in normal mode
    (screenshots taken before/after).
  • Also checked the adjacent .improvedtube-player-button:hover::after
    tooltip style (used for the buttons below the player, e.g. Loop/PiP/
    Screenshot) — untouched by this change, no regression there.
  • Added tests/unit/tooltip-fullscreen-stacking.test.js: behavioral unit
    tests that extract the real createPlayerButton source, run it in a vm
    sandbox against a fake DOM, fire a real mouseover, and assert where the
    tooltip actually gets parented — covering document.fullscreenElement,
    the webkit/moz-prefixed fallbacks, the non-fullscreen document.body
    case, and that mouseleave still cleans up a reparented tooltip. Three of
    the four tests fail against the pre-fix code, confirming they're real
    regression coverage, not just source-text assertions.
  • npm run lint — clean, no errors.
  • npm test — 25 suites / 117 tests passed.
  • This branch also went through this repo's own no-mistakes validation
    pipeline (independent review, test, lint, and doc gates) end-to-end, which
    passed and additionally suggested the vendor-prefix fallback and the
    stronger behavioral tests above — both incorporated.

Anything I was unsure about

I was not able to get the packaged extension itself to load in this
sandboxed browser-automation environment: --load-extension +
--disable-extensions-except is present in Chrome's actual command line
(verified via chrome://version), and I also confirmed Developer Mode was
genuinely persisted on in the profile (chrome://extensions), but
chrome://extensions still reports 0 installed items either way, and no
error card appears. This looks like the automation harness's Chrome
(--enable-automation) suppressing unpacked-extension loading rather than
anything about this extension's manifest.

Because of that, "live" verification here was done by pulling the actual,
current ImprovedTube.createPlayerButton function verbatim out of
js&css/web-accessible/functions.js (post-fix) plus the real
.it-player-button--tooltip CSS from styles.css, and executing that exact
code, unmodified, against a real youtube.com/watch page — creating the
real playback-speed button, dispatching a real mouseover, and entering
real browser Fullscreen (Element.requestFullscreen(), the same API
YouTube's own fullscreen button uses). Screenshots confirm the tooltip is
invisible in fullscreen before the fix and clearly visible above the video
in fullscreen after it, with no change in normal/theater mode. This
exercises the identical code path a loaded extension would run; the one gap
is that it wasn't driven through the packaged extension's content-script
injection itself. A maintainer with a normal desktop Chrome/Firefox profile
may still want to do one final sanity check loading the built extension for
real, though the root cause (Fullscreen API only paints the fullscreen
element's subtree) is browser-spec-defined and not environment-specific.

This change was AI-assisted.

Custom player-button tooltips (e.g. the playback speed button) are
appended to document.body. Once the player enters the browser's
Fullscreen API, only the fullscreen element's subtree is painted, so
a tooltip parented to document.body renders behind the video instead
of above it.

Append the tooltip to document.fullscreenElement when one is active,
falling back to document.body otherwise.

Fixes code-charity#4294
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

🐞Tooltips are hidden behind the video player

1 participant