Spaces:
Running
Running
File size: 3,507 Bytes
cc2caf9 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
import React, { useState, useRef, useEffect } from 'react';
import ContentCard from './ContentCard';
import { ChevronLeft, ChevronRight } from 'lucide-react';
interface ContentItem {
type: 'movie' | 'tvshow';
title: string;
image: string;
description?: string;
genre?: string[];
year?: number | string;
}
interface ContentRowProps {
title: string;
items: ContentItem[];
}
const ContentRow: React.FC<ContentRowProps> = ({ title, items }) => {
const rowRef = useRef<HTMLDivElement>(null);
const [showLeftButton, setShowLeftButton] = useState(false);
const [showRightButton, setShowRightButton] = useState(true);
// Handle scroll events to show/hide buttons
const handleScroll = () => {
if (rowRef.current) {
const { scrollLeft, scrollWidth, clientWidth } = rowRef.current;
setShowLeftButton(scrollLeft > 20);
setShowRightButton(scrollLeft < scrollWidth - clientWidth - 20);
}
};
// Set up scroll listeners and initial state
useEffect(() => {
handleScroll();
window.addEventListener('resize', handleScroll);
return () => window.removeEventListener('resize', handleScroll);
}, [items]);
const scroll = (direction: 'left' | 'right') => {
if (rowRef.current) {
const card = rowRef.current.querySelector('.card-hover');
const cardWidth = card ? card.clientWidth + 16 : 280; // Card width + margin
const scrollAmount = direction === 'left' ? -cardWidth * 3 : cardWidth * 3;
rowRef.current.scrollBy({ left: scrollAmount, behavior: 'smooth' });
}
};
// Don't render the row if there are no items
if (items.length === 0) {
return null;
}
return (
<div className="content-row mb-8">
<h2 className="text-xl font-bold px-4 md:px-8 mb-4">{title}</h2>
<div className="relative group">
{/* Left scroll button */}
<button
onClick={() => scroll('left')}
className={`absolute left-2 top-1/2 transform -translate-y-1/2 z-30
bg-black/40 hover:bg-black/60 rounded-full p-2 transition-all duration-200
${showLeftButton ? 'opacity-100' : 'opacity-0 pointer-events-none'}`}
aria-label="Scroll left"
>
<ChevronLeft className="w-6 h-6 text-white" />
</button>
{/* Content row */}
<div
ref={rowRef}
onScroll={handleScroll}
className="flex gap-4 overflow-x-auto py-4 px-4 md:px-8 scrollbar-none scroll-smooth"
style={{ scrollbarWidth: 'none' }}
>
{items.map((item, index) => (
<div key={`${item.title}-${index}`} className="flex-shrink-0">
<ContentCard
type={item.type}
title={item.title}
image={item.image}
description={item.description}
genre={item.genre}
year={item.year}
/>
</div>
))}
</div>
{/* Right scroll button */}
<button
onClick={() => scroll('right')}
className={`absolute right-2 top-1/2 transform -translate-y-1/2 z-30
bg-black/40 hover:bg-black/60 rounded-full p-2 transition-all duration-200
${showRightButton ? 'opacity-100' : 'opacity-0 pointer-events-none'}`}
aria-label="Scroll right"
>
<ChevronRight className="w-6 h-6 text-white" />
</button>
</div>
</div>
);
};
export default ContentRow;
|