YouTube Auto-Hide Progress Bar

Auto-hide YouTube video player controls and progress bar. Hover to reveal.

// ==UserScript==
// @name         YouTube Auto-Hide Progress Bar
// @description  Auto-hide YouTube video player controls and progress bar. Hover to reveal.
// @namespace    https://github.com/sonnenfell/Hide-YouTube-Progress-Bar
// @version      1.5.2 - Bug Fix
// @license      GPL-3.0
// @icon         https://www.google.com/s2/favicons?sz=64&domain=youtube.com
// @author       Sunfur
// @match        https://www.youtube.com/*
// @grant        none
// ==/UserScript==
let hoverToggle;
let isHoverInLowerPosition = true;
let onlyOnPause = true; // If you want this scripts auto-hide feature to override YouTube's even while the video is not paused, simply replace "let onlyOnPause = true;" with "let onlyOnPause = false;"

const setupHoverToggle = () => {
    const player = document.querySelector('.html5-video-player');
    if (!player || hoverToggle) return;

    player.style.position = 'relative';

    hoverToggle = document.createElement('div');
    hoverToggle.style.position = 'absolute';
    hoverToggle.style.left = '0';
    hoverToggle.style.width = '100%';
    hoverToggle.style.zIndex = '9998';
    hoverToggle.style.pointerEvents = 'auto';
    hoverToggle.style.background = 'transparent';

    player.appendChild(hoverToggle);
};

const observer = new MutationObserver(() => {
    const video = document.querySelector('video');
    const player = document.querySelector('.html5-video-player');
    const progressBar = document.querySelector('.ytp-progress-bar');
    const controls = document.querySelector('.ytp-chrome-bottom');

    if (!video || !player || !progressBar || !controls) return;

    setupHoverToggle();

    const updateVisibility = () => {
        if (!isHoverInLowerPosition) return;

        progressBar.style.opacity = '0';
        controls.style.opacity = '0';
        controls.style.pointerEvents = 'none';

        hoverToggle.style.bottom = '0';
        hoverToggle.style.height = '14%';
        isHoverInLowerPosition = true;
    };

    if (!onlyOnPause) {
    updateVisibility();
    } else if (video.paused) {
      updateVisibility();
    };

    hoverToggle.onmouseenter = () => {
        const isVisible = controls.style.opacity === '1';

        if (!onlyOnPause || video.paused) {
          if (!isVisible) {
              progressBar.style.opacity = '1';
              controls.style.opacity = '1';
              controls.style.pointerEvents = 'auto';

              hoverToggle.style.bottom = '17%';
              hoverToggle.style.height = '5%';
              isHoverInLowerPosition = false;
          } else {
              progressBar.style.opacity = '0';
              controls.style.opacity = '0';
              controls.style.pointerEvents = 'none';

              hoverToggle.style.bottom = '0';
              hoverToggle.style.height = '14%';
              isHoverInLowerPosition = true;
          }
        }
        else {
            progressBar.style.removeProperty('opacity');
            controls.style.removeProperty('opacity');
            controls.style.removeProperty('pointer-events');
            hoverToggle.style.height = '2%';
        }
    };
});

observer.observe(document.body, { childList: true, subtree: true });