Fix overlay to use Plyr's built-in poster element

Instead of custom overlay, use Plyr's .plyr__poster element which:
- Naturally covers the iframe when paused/initial load
- Allows Plyr controls to receive clicks (z-index hierarchy)
- Hides (opacity: 0) when playing, shows (opacity: 1) when paused
- Blocks YouTube UI interactions when visible

This matches the reference implementation behavior.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
dwindown
2026-01-01 01:33:22 +07:00
parent 0df57bbac5
commit b335164a58

View File

@@ -34,6 +34,7 @@ export const VideoPlayerWithChapters = forwardRef<VideoPlayerRef, VideoPlayerWit
const videoRef = useRef<HTMLVideoElement>(null);
const wrapperRef = useRef<HTMLDivElement>(null);
const playerRef = useRef<Plyr | null>(null);
const posterRef = useRef<HTMLDivElement | null>(null);
const [currentChapterIndex, setCurrentChapterIndex] = useState<number>(-1);
const [isPlaying, setIsPlaying] = useState<boolean>(false);
@@ -93,12 +94,32 @@ export const VideoPlayerWithChapters = forwardRef<VideoPlayerRef, VideoPlayerWit
playerRef.current = player;
// Track play/pause state to show/hide overlay
player.on('play', () => setIsPlaying(true));
player.on('pause', () => setIsPlaying(false));
player.on('ended', () => setIsPlaying(false));
// Get poster element
posterRef.current = player.elements.wrapper.querySelector('.plyr__poster') as HTMLDivElement;
// Apply custom accent color
// Track play/pause state to show/hide poster overlay
player.on('play', () => {
setIsPlaying(true);
if (posterRef.current) {
posterRef.current.style.opacity = '0';
}
});
player.on('pause', () => {
setIsPlaying(false);
if (posterRef.current) {
posterRef.current.style.opacity = '1';
}
});
player.on('ended', () => {
setIsPlaying(false);
if (posterRef.current) {
posterRef.current.style.opacity = '1';
}
});
// Apply custom accent color and poster styles
if (accentColor) {
const style = document.createElement('style');
style.textContent = `
@@ -114,6 +135,11 @@ export const VideoPlayerWithChapters = forwardRef<VideoPlayerRef, VideoPlayerWit
.plyr__progress__buffer {
color: ${accentColor}40 !important;
}
/* Poster overlay to block YouTube UI when paused */
.plyr__poster {
background-color: transparent !important;
transition: opacity 0.3s ease;
}
`;
document.head.appendChild(style);
@@ -200,22 +226,12 @@ export const VideoPlayerWithChapters = forwardRef<VideoPlayerRef, VideoPlayerWit
return (
<div ref={wrapperRef} className={`plyr__video-embed relative ${className}`}>
{youtubeId && (
<>
{/* CSS Overlay to block YouTube UI interactions - shows when paused */}
<div
className="absolute inset-0 z-10"
style={{
background: 'transparent',
pointerEvents: isPlaying ? 'none' : 'auto'
}}
/>
<iframe
src={`https://www.youtube-nocookie.com/embed/${youtubeId}?origin=${window.location.origin}&iv_load_policy=3&modestbranding=1&playsinline=1&rel=0&showinfo=0&controls=0&disablekb=1&fs=0`}
allowFullScreen
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
style={{ pointerEvents: 'none' }}
className="pointer-events-none"
/>
</>
)}
</div>
);