Naslovnica: mobilni mozaik (2 mali + 1 siroka, nato 1 velika + 2 mali), desktop nespremenjen
This commit is contained in:
parent
3c6079d720
commit
6f4cfa8ee9
@ -148,6 +148,77 @@ function getObjectPosition(coverImage: string | null, focalPoints?: Record<strin
|
||||
return `${fp.x}% ${fp.y}%`;
|
||||
}
|
||||
|
||||
function MosaicTile({ article, focalPoints, tall = false }: { article: Article; focalPoints?: Record<string, { x: number; y: number }>; tall?: boolean }) {
|
||||
const objPos = getObjectPosition(article.coverImage, focalPoints);
|
||||
return (
|
||||
<Link href={`/article/${article.slug}`}>
|
||||
<div className="relative rounded-lg overflow-hidden" data-testid={`tile-mosaic-${article.id}`}>
|
||||
<img
|
||||
src={thumbUrl(article.coverImage)}
|
||||
alt={article.title}
|
||||
className={`w-full object-cover ${tall ? "aspect-[16/10]" : "aspect-square"}`}
|
||||
style={{ objectPosition: objPos }}
|
||||
loading="lazy"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-black/85 via-black/30 to-transparent" />
|
||||
<span className="absolute top-2 left-2 bg-primary text-white text-[10px] font-semibold px-2 py-0.5 rounded">
|
||||
{article.category || "News"}
|
||||
</span>
|
||||
<h3 className={`absolute bottom-2 left-2 right-2 text-white font-semibold leading-snug ${tall ? "text-base line-clamp-2" : "text-xs line-clamp-3"}`}>
|
||||
{article.title}
|
||||
</h3>
|
||||
</div>
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
function MosaicHeading({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<div className="mb-3">
|
||||
<h2 className="text-primary font-bold text-lg leading-none mb-2">{children}</h2>
|
||||
<div className="h-0.5 w-16 bg-primary" />
|
||||
<div className="h-px w-full bg-card-border -mt-px" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function MobileMosaic({ latest, popular, focalPoints }: { latest: Article[]; popular?: Article[]; focalPoints?: Record<string, { x: number; y: number }> }) {
|
||||
const l = (latest || []).slice(0, 3);
|
||||
if (l.length === 0) return null;
|
||||
const p = (popular || []).filter((a) => !l.some((x) => x.id === a.id)).slice(0, 3);
|
||||
return (
|
||||
<div className="md:hidden space-y-6" data-testid="section-mobile-mosaic">
|
||||
<section>
|
||||
<MosaicHeading>Neueste Artikel</MosaicHeading>
|
||||
<div className="grid grid-cols-2 gap-2">
|
||||
{l.slice(0, 2).map((a) => (
|
||||
<MosaicTile key={a.id} article={a} focalPoints={focalPoints} />
|
||||
))}
|
||||
</div>
|
||||
{l[2] && (
|
||||
<div className="mt-2">
|
||||
<MosaicTile article={l[2]} focalPoints={focalPoints} tall />
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
|
||||
{p.length > 0 && (
|
||||
<section>
|
||||
<MosaicHeading>Beliebt</MosaicHeading>
|
||||
<MosaicTile article={p[0]} focalPoints={focalPoints} tall />
|
||||
{p.length > 1 && (
|
||||
<div className="grid grid-cols-2 gap-2 mt-2">
|
||||
{p.slice(1, 3).map((a) => (
|
||||
<MosaicTile key={a.id} article={a} focalPoints={focalPoints} />
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function MediumCard({ article, focalPoints }: { article: Article; focalPoints?: Record<string, { x: number; y: number }> }) {
|
||||
const isVideo = article.category === "Video";
|
||||
const objPos = getObjectPosition(article.coverImage, focalPoints);
|
||||
@ -707,7 +778,14 @@ export default function Home() {
|
||||
|
||||
<div className="grid grid-cols-1 lg:grid-cols-4 gap-4">
|
||||
<div className="lg:col-span-3 space-y-4">
|
||||
<FeaturedCarousel articles={articles.filter(a => a.featured)} popular={popular} galleryImages={galleryImages} focalPoints={focalPoints} />
|
||||
<div className="hidden md:block">
|
||||
<FeaturedCarousel articles={articles.filter(a => a.featured)} popular={popular} galleryImages={galleryImages} focalPoints={focalPoints} />
|
||||
</div>
|
||||
<MobileMosaic
|
||||
latest={[...articles].sort((a, b) => new Date(b.publishedAt).getTime() - new Date(a.publishedAt).getTime())}
|
||||
popular={popular}
|
||||
focalPoints={focalPoints}
|
||||
/>
|
||||
</div>
|
||||
<div className="lg:col-span-1 space-y-4">
|
||||
<SidebarWeatherWidget />
|
||||
|
||||
Loading…
Reference in New Issue
Block a user