Polish portfolio, blog, and site chrome for clearer browsing.

Add patterned title bands, lightbox gallery, project link bar, footer stats/credit, gradient link hovers, and more reliable blog covers/body rendering.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Alireza Hassani
2026-08-23 22:17:25 +03:30
co-authored by Cursor
parent 37d8e4be91
commit 908d86939c
19 changed files with 710 additions and 193 deletions
+73 -41
View File
@@ -4,6 +4,7 @@ import { notFound } from "next/navigation";
import { ContentPageShell } from "@/components/ContentPageShell";
import { HtmlContent } from "@/components/HtmlContent";
import { PortfolioGallery } from "@/components/PortfolioGallery";
import { PortfolioProjectLink } from "@/components/PortfolioProjectLink";
import {
categoryLabelFa,
findPortfolioCategory,
@@ -103,58 +104,82 @@ export default async function PortfolioDetailPage({
(item) => item.url !== cover,
);
const titleEn =
portfolio.titleEn ??
(portfolio.titleFa && portfolio.title !== portfolio.titleFa
? portfolio.title
: null);
const categoryHref = rootCategory
? portfolioCategoryHref(rootCategory.slug)
: "/portfolio";
return (
<ContentPageShell>
<ContentPageShell flushTop>
<article className="pb-20 lg:pb-28">
<div className="mx-auto max-w-5xl px-5 lg:px-8">
<div className="reveal mb-10 max-w-3xl">
<Link
href={
rootCategory
? portfolioCategoryHref(rootCategory.slug)
: "/portfolio"
}
className="link-hover mb-6 inline-flex text-sm text-muted"
>
بازگشت به نمونه‌کارها
</Link>
{categoryFa ? (
<p className="mb-3 text-[11px] text-muted">{categoryFa}</p>
) : null}
<h1 className="whitespace-normal text-[clamp(1.35rem,3.8vw,2.5rem)] font-normal leading-tight tracking-tight text-ink">
{title}
</h1>
{portfolio.titleEn ? (
<p className="latin title-en text-muted">
{portfolio.titleEn}
</p>
) : null}
{portfolio.abstract ? (
<p className="mt-5 text-justify text-sm leading-8 text-muted md:text-base">
{portfolio.abstract}
</p>
) : null}
{date ? (
<time
className="mt-5 block text-xs text-muted"
dateTime={portfolio.publishedAt ?? undefined}
<div className="page-title-band mb-8 md:mb-10">
<div className="relative mx-auto max-w-7xl px-5 pb-4 pt-[calc(var(--header-height)+0.75rem)] lg:px-8 lg:pb-5 lg:pt-[calc(var(--header-height)+1rem)]">
{titleEn ? (
<p
aria-hidden
className="latin pointer-events-none absolute inset-x-5 top-[calc(var(--header-height)+2.4rem)] z-0 text-[clamp(1.75rem,5.5vw,3.75rem)] font-light uppercase leading-none tracking-[0.05em] text-ink/[0.07] lg:inset-x-8 lg:top-[calc(var(--header-height)+2.6rem)]"
>
{date}
</time>
{titleEn}
</p>
) : null}
</div>
<div className="reveal relative z-10 max-w-3xl">
<nav
aria-label="مسیر صفحه"
className="mb-3 flex flex-wrap items-center gap-1.5 text-xs text-muted"
>
<Link
href="/portfolio"
className="link-hover transition hover:text-ink"
>
نمونه‌کارها
</Link>
{rootCategory || categoryFa ? (
<>
<span aria-hidden className="text-line">
/
</span>
<Link
href={categoryHref}
className="link-hover transition hover:text-ink"
>
{rootCategory?.nameFa ?? categoryFa}
</Link>
</>
) : null}
<span aria-hidden className="text-line">
/
</span>
<span className="line-clamp-1 text-ink-soft">{title}</span>
</nav>
<h1 className="whitespace-normal text-[clamp(1.35rem,3.8vw,2.5rem)] font-normal leading-tight tracking-tight text-ink">
{title}
</h1>
{portfolio.abstract ? (
<p className="mt-2 text-justify text-sm leading-7 text-muted md:text-base">
{portfolio.abstract}
</p>
) : null}
</div>
</div>
</div>
<div className="mx-auto max-w-5xl px-5 lg:px-8">
<PortfolioGallery
cover={cover}
images={gallery.map((item) => ({
id: item.mediaId,
url: item.url,
}))}
category={categoryFa}
date={date}
dateTime={portfolio.publishedAt}
/>
{portfolio.mainTextHtml ? (
@@ -163,6 +188,13 @@ export default async function PortfolioDetailPage({
</div>
) : null}
</div>
{portfolio.projectUrl ? (
<PortfolioProjectLink
url={portfolio.projectUrl}
title={title}
/>
) : null}
</article>
</ContentPageShell>
);