diff --git a/client/src/components/video-card.tsx b/client/src/components/video-card.tsx index a447925..960f9b5 100644 --- a/client/src/components/video-card.tsx +++ b/client/src/components/video-card.tsx @@ -1,6 +1,7 @@ import { Play } from "lucide-react"; import { type Video } from "@shared/schema"; import HLSPreviewThumbnail from "./hls-preview-thumbnail"; +import { useState, useRef, useEffect } from "react"; interface VideoCardProps { video: Video; @@ -42,20 +43,47 @@ function formatDate(date: Date | string): string { } export default function VideoCard({ video, onClick, className = "" }: VideoCardProps) { + const [isHovered, setIsHovered] = useState(false); + const [showPreview, setShowPreview] = useState(false); + const hoverTimeoutRef = useRef(); + + // Delay preview start to avoid loading on quick mouse passes + useEffect(() => { + if (isHovered) { + hoverTimeoutRef.current = setTimeout(() => { + setShowPreview(true); + }, 800); // Start preview after 800ms hover + } else { + if (hoverTimeoutRef.current) { + clearTimeout(hoverTimeoutRef.current); + } + setShowPreview(false); + } + + return () => { + if (hoverTimeoutRef.current) { + clearTimeout(hoverTimeoutRef.current); + } + }; + }, [isHovered]); + return (
setIsHovered(true)} + onMouseLeave={() => setIsHovered(false)} > - {/* Simple thumbnail with fallback - no HLS loading until needed */} + {/* Video preview container */}
onClick?.(video)} > + {/* Static thumbnail - always visible */} {video.title} + {/* Video preview - only load when hovering */} + {showPreview && ( +
+ +
+ )} + {/* Duration badge */} -
+
{formatDuration(video.duration)}
- - - {/* Play button overlay */} -
-
-
+ {/* Play button overlay - hidden during preview */} + {!showPreview && ( +
+
+
+
-
+ )}