104 أسطر
3.2 KiB
TypeScript
104 أسطر
3.2 KiB
TypeScript
import Image from "next/image";
|
|
|
|
type ProjectCardProps = {
|
|
project: {
|
|
id: string;
|
|
title: string;
|
|
location: string;
|
|
year: string;
|
|
area: string;
|
|
role: string;
|
|
description: string;
|
|
highlights: readonly string[];
|
|
image: string;
|
|
sheetImage?: string;
|
|
imageAlt: string;
|
|
};
|
|
reverse?: boolean;
|
|
priority?: boolean;
|
|
labels?: {
|
|
year: string;
|
|
area: string;
|
|
role: string;
|
|
fullSheet: string;
|
|
};
|
|
};
|
|
|
|
export function ProjectCard({
|
|
project,
|
|
reverse = false,
|
|
priority = false,
|
|
labels,
|
|
}: ProjectCardProps) {
|
|
return (
|
|
<article
|
|
className={`project-card-shell grid gap-8 rounded-[34px] border p-4 md:p-5 lg:grid-cols-[0.78fr_1fr] lg:items-center lg:gap-14 ${
|
|
reverse ? "lg:[&>*:first-child]:order-2 lg:[&>*:last-child]:order-1" : ""
|
|
}`}
|
|
>
|
|
<div className="image-frame mx-auto w-full max-w-[540px]">
|
|
<div className="relative aspect-[3/5] overflow-hidden rounded-[26px]">
|
|
<Image
|
|
src={project.image}
|
|
alt={project.imageAlt}
|
|
fill
|
|
sizes="(max-width: 1024px) 100vw, 540px"
|
|
className="bg-white object-cover transition-transform duration-700 hover:scale-[1.03]"
|
|
priority={priority}
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="flex flex-col justify-center">
|
|
<div className="type-label-wide flex flex-wrap items-center gap-x-3 gap-y-2 text-[var(--color-muted)] sm:flex-nowrap">
|
|
<span>{project.id}</span>
|
|
<span className="project-rule-line h-px w-12 shrink-0" />
|
|
<span>{project.location}</span>
|
|
</div>
|
|
|
|
<h3 className="type-project-title mt-5 text-[var(--color-ink)]">
|
|
{project.title}
|
|
</h3>
|
|
<p className="type-body-responsive mt-5 max-w-xl text-[var(--color-muted)]">
|
|
{project.description}
|
|
</p>
|
|
|
|
<dl className="project-meta-list mt-8 grid gap-4 border-y py-6 sm:grid-cols-3">
|
|
<div>
|
|
<dt className="eyebrow-note">{labels?.year ?? "Year"}</dt>
|
|
<dd className="type-body mt-2 font-semibold text-[var(--color-ink)]">{project.year}</dd>
|
|
</div>
|
|
<div>
|
|
<dt className="eyebrow-note">{labels?.area ?? "Area"}</dt>
|
|
<dd className="type-body mt-2 font-semibold text-[var(--color-ink)]">{project.area}</dd>
|
|
</div>
|
|
<div>
|
|
<dt className="eyebrow-note">{labels?.role ?? "Role"}</dt>
|
|
<dd className="type-body mt-2 font-semibold text-[var(--color-ink)]">{project.role}</dd>
|
|
</div>
|
|
</dl>
|
|
|
|
<ul className="type-chip mt-8 grid gap-3 text-[var(--color-muted)] sm:grid-cols-2">
|
|
{project.highlights.map((highlight) => (
|
|
<li key={highlight} className="flex items-center gap-3">
|
|
<span className="h-2 w-2 rounded-full bg-[var(--color-blue-500)]" />
|
|
<span>{highlight}</span>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
|
|
{project.sheetImage ? (
|
|
<a
|
|
href={project.sheetImage}
|
|
className="button-secondary mt-8 w-fit"
|
|
target="_blank"
|
|
rel="noreferrer"
|
|
>
|
|
{labels?.fullSheet ?? "View full sheet"}
|
|
</a>
|
|
) : null}
|
|
</div>
|
|
</article>
|
|
);
|
|
}
|