Match highlights: fullscreen landscape drawer (narrow + clear glass)

Native fullscreen paints only #ytpWrap and its descendants, so the Highlights
pane was invisible in fullscreen. On fullscreenchange the pane is now relocated
INTO the player (and moved back on exit), and CSS reshapes it into a narrow,
transparent right-side drawer:

- Blurred-glass background (Clear) + text shadows so it barely covers the match
  while staying readable; @supports fallback firms up the fill where
  backdrop-filter is unsupported.
- Width clamp(230px, 30vw, 360px) — the Narrow choice, usable on any screen.
- While open: player controls + gradient pull in to the video area (scrubber
  never hidden), coach caption stays bottom-left, and the Highlights button
  slides to the drawer's left edge so it stays tappable to close.
- Same pane/data/tabs/CRUD; windowed bottom-sheet behavior unchanged.

Note: iPhone Safari forces native <video> fullscreen (no custom UI), so the
drawer applies where element fullscreen is supported (Android, desktop, iPad).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
ghassan 2026-07-28 23:16:50 +03:00
parent cffd8491d0
commit f8cefc1bf9

View File

@ -1971,6 +1971,56 @@
.yt-bottom-nav, .yt-bottom-nav,
#main.yt-main { transition: none; } #main.yt-main { transition: none; }
} }
/* ============================================================
MATCH HIGHLIGHTS fullscreen landscape drawer
Native fullscreen renders only #ytpWrap + descendants, so JS
relocates the pane inside the player and it becomes a Narrow,
Clear (blurred-glass) right-side drawer that barely covers the
match. Applies at any width, only while .ytp-fullscreen is on.
============================================================ */
.ytp-wrap.ytp-fullscreen { --hl-drawer-w: clamp(230px, 30vw, 360px); }
.ytp-wrap.ytp-fullscreen .events-sidebar {
display: flex !important;
position: absolute; top: 0; right: 0; bottom: 0; left: auto;
width: var(--hl-drawer-w);
height: auto !important; max-height: none !important;
margin: 0 !important; border-radius: 0 !important;
background: linear-gradient(to left, rgba(10, 10, 13, 0.42), rgba(10, 10, 13, 0.14));
-webkit-backdrop-filter: blur(7px); backdrop-filter: blur(7px);
border-left: 1px solid rgba(255, 255, 255, 0.10);
box-shadow: none;
text-shadow: 0 1px 4px rgba(0, 0, 0, 0.85); /* legibility over the video */
transform: translateX(100%);
transition: transform 0.34s cubic-bezier(0.32, 0.72, 0, 1);
pointer-events: none; z-index: 40;
}
.ytp-wrap.ytp-fullscreen .events-sidebar.show { transform: translateX(0); pointer-events: auto; }
.ytp-wrap.ytp-fullscreen .events-sidebar .hl-sheet-grab { display: none; }
/* Fallback where backdrop-filter is unsupported firm up the fill so the
list stays readable over the video. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
.ytp-wrap.ytp-fullscreen .events-sidebar {
background: linear-gradient(to left, rgba(10, 10, 13, 0.74), rgba(10, 10, 13, 0.52));
}
}
/* While the drawer is open: pull the controls into the video area so the
scrubber isn't hidden, keep the coach caption in the video area, and slide
the Highlights button to the drawer's left edge so it stays tappable. */
.ytp-wrap.ytp-fullscreen.hl-drawer-open .ytp-chrome-bottom,
.ytp-wrap.ytp-fullscreen.hl-drawer-open .ytp-gradient-bottom { right: var(--hl-drawer-w) !important; }
.ytp-wrap.ytp-fullscreen.hl-drawer-open .coach-note-overlay {
left: 16px; right: auto; transform: none; max-width: 60%;
}
.ytp-wrap.ytp-fullscreen.hl-drawer-open .match-highlights-toggle {
right: calc(var(--hl-drawer-w) + 10px);
}
@media (prefers-reduced-motion: reduce) {
.ytp-wrap.ytp-fullscreen .events-sidebar { transition: none; }
}
</style> </style>
@endsection @endsection
@ -2314,6 +2364,7 @@
const backdrop = document.getElementById('hlSheetBackdrop'); const backdrop = document.getElementById('hlSheetBackdrop');
const grab = sidebar.querySelector('.hl-sheet-grab'); const grab = sidebar.querySelector('.hl-sheet-grab');
const mainScroll = document.getElementById('main'); const mainScroll = document.getElementById('main');
const player = document.getElementById('ytpWrap');
const isMobile = () => window.matchMedia('(max-width: 991px)').matches; const isMobile = () => window.matchMedia('(max-width: 991px)').matches;
// Pin the sheet's top edge to the player's exact bottom so the // Pin the sheet's top edge to the player's exact bottom so the
@ -2330,6 +2381,8 @@
const setOpen = (open) => { const setOpen = (open) => {
sidebar.classList.toggle('show', open); sidebar.classList.toggle('show', open);
toggleBtn.classList.toggle('expanded', open); toggleBtn.classList.toggle('expanded', open);
// Fullscreen drawer state — harmless when not fullscreen (CSS is gated).
if (player) player.classList.toggle('hl-drawer-open', open);
if (backdrop) backdrop.classList.toggle('show', open && isMobile()); if (backdrop) backdrop.classList.toggle('show', open && isMobile());
// Hide the top bar (mobile only) to give the player more room. // Hide the top bar (mobile only) to give the player more room.
document.body.classList.toggle('hl-sheet-open', open && isMobile()); document.body.classList.toggle('hl-sheet-open', open && isMobile());
@ -2364,6 +2417,30 @@
document.body.classList.toggle('hl-sheet-open', openMobile); document.body.classList.toggle('hl-sheet-open', openMobile);
positionSheet(); positionSheet();
}); });
// Fullscreen: native fullscreen paints only #ytpWrap and its
// descendants, so the pane must live INSIDE the player to be
// visible. Relocate it there on enter, move it home on exit; CSS
// reshapes it into the transparent right-side drawer.
if (player) {
let fsHome = null;
const onFsChange = () => {
const fsEl = document.fullscreenElement || document.webkitFullscreenElement;
const inPlayerFs = fsEl === player;
if (inPlayerFs && !fsHome) {
fsHome = document.createComment('events-sidebar-home');
sidebar.parentNode.insertBefore(fsHome, sidebar);
player.appendChild(sidebar);
player.classList.toggle('hl-drawer-open', sidebar.classList.contains('show'));
} else if (!inPlayerFs && fsHome) {
fsHome.parentNode.insertBefore(sidebar, fsHome);
fsHome.parentNode.removeChild(fsHome);
fsHome = null;
}
};
document.addEventListener('fullscreenchange', onFsChange);
document.addEventListener('webkitfullscreenchange', onFsChange);
}
} }
}); });
</script> </script>