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:
@@ -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' }}
|
||||
/>
|
||||
</>
|
||||
<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"
|
||||
className="pointer-events-none"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user