File size: 1,519 Bytes
38ee3c1 f0b240d 38ee3c1 f0b240d 38ee3c1 f0b240d 0f0ce9b f0b240d 38ee3c1 f0b240d | 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 | import { useI18n } from "../i18n/I18nContext";
import type { SuggestedVideo } from "../types/api";
type Props = {
videos: SuggestedVideo[];
activeId: string | null;
loadingId: string | null;
onSelect: (video: SuggestedVideo) => void;
};
export function SuggestedRail({ videos, activeId, loadingId, onSelect }: Props) {
const { t } = useI18n();
return (
<aside className="suggested-rail">
<p className="rail-title">{t.watch.upNext}</p>
{videos.map((v) => (
<button
key={v.id}
type="button"
className={`suggested-card ${activeId === v.id ? "active" : ""}`}
onClick={() => onSelect(v)}
disabled={loadingId === v.id}
>
<img
src={v.thumbnail_url}
alt=""
className="suggested-thumb"
onError={(e) => {
const img = e.currentTarget;
if (!img.dataset.fallback) {
img.dataset.fallback = "1";
img.src = `https://i.ytimg.com/vi/${v.id}/hqdefault.jpg`;
}
}}
/>
<div className="suggested-info">
<p className="suggested-title">{v.title}</p>
<p className="suggested-channel">{v.channel_title}</p>
{!v.embeddable && <span className="embed-badge">{t.watch.externalOnly}</span>}
{loadingId === v.id && <span className="loading-tag">{t.watch.loadingComments}</span>}
</div>
</button>
))}
</aside>
);
}
|