chore: code refactor
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
"use client";
|
||||
|
||||
/**
|
||||
* CollectionGridCard — square collection card for the 2-per-row grid view.
|
||||
*
|
||||
* • With cover: cover fills the square; bottom-up overlay for legibility.
|
||||
* • Without cover: the same flat palette-aware surface that post cards
|
||||
* fall back to — pure white on light themes, palette-specific dark
|
||||
* contrast on dark themes (see `--quote-card-bg`).
|
||||
*
|
||||
* Visibility badge (Globe/Lock) sits top-right. Title + count read
|
||||
* bottom-centre in white over the cover image's dark overlay; on the
|
||||
* flat fallback they use `text-foreground` so they invert cleanly with
|
||||
* the theme.
|
||||
*/
|
||||
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
import { Lock } from "lucide-react";
|
||||
import { cn } from "@/lib/utils";
|
||||
import type { Collection } from "@/lib/social";
|
||||
import { quoteCardBgStyle } from "../post/post-card-shared";
|
||||
|
||||
export function CollectionGridCard({
|
||||
collection: c,
|
||||
href,
|
||||
}: {
|
||||
collection: Collection;
|
||||
href: string;
|
||||
}) {
|
||||
const hasCover = !!c.cover_url;
|
||||
return (
|
||||
<Link
|
||||
href={href}
|
||||
className="group relative block aspect-square rounded-2xl overflow-hidden ring-1 ring-foreground/10 hover:ring-foreground/25 hover:shadow-md transition-all select-none"
|
||||
>
|
||||
{hasCover ? (
|
||||
<>
|
||||
<Image
|
||||
src={c.cover_url!}
|
||||
alt=""
|
||||
fill
|
||||
sizes="(max-width: 640px) 50vw, 320px"
|
||||
className="object-cover"
|
||||
unoptimized
|
||||
/>
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-black/80 via-black/30 to-transparent" />
|
||||
</>
|
||||
) : (
|
||||
<div className="absolute inset-0" style={quoteCardBgStyle()} />
|
||||
)}
|
||||
|
||||
{/* Visibility badge — black pill works on both image overlay and
|
||||
flat surface (white or dark). */}
|
||||
{c.is_public ? null : (
|
||||
<div className="absolute top-3 right-3 inline-flex items-center gap-1 rounded-full bg-black/40 backdrop-blur-sm px-2.5 py-1 text-[0.6rem] uppercase tracking-[0.18em] font-medium text-white">
|
||||
<Lock className="size-3" />
|
||||
{"Private"}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Title + count — text colour follows the surface beneath. */}
|
||||
<div
|
||||
className={cn(
|
||||
"absolute inset-0 flex flex-col items-center justify-center text-center px-5 sm:px-7",
|
||||
hasCover ? "text-white" : "text-foreground",
|
||||
)}
|
||||
>
|
||||
<p
|
||||
className={cn(
|
||||
"font-[family-name:var(--font-title)] text-lg sm:text-2xl font-semibold leading-snug line-clamp-4 break-words",
|
||||
hasCover && "drop-shadow-sm",
|
||||
)}
|
||||
>
|
||||
{c.title}
|
||||
</p>
|
||||
<p
|
||||
className={cn(
|
||||
"mt-2 text-[0.65rem] uppercase tracking-[0.22em] font-medium",
|
||||
hasCover ? "text-white/85" : "text-muted-foreground",
|
||||
)}
|
||||
>
|
||||
{c.item_count} post{c.item_count === 1 ? "" : "s"}
|
||||
</p>
|
||||
</div>
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user