90 lines
3.5 KiB
TypeScript
90 lines
3.5 KiB
TypeScript
import { LinkList } from '#web-runtime/components/links';
|
|
import { MediaImage } from '#web-runtime/components/media-image';
|
|
import { RichTextContent } from '#web-runtime/components/rich-text';
|
|
import type { PageDocument } from '#web-runtime/types';
|
|
|
|
export default function PageHero({ page }: { page: PageDocument }) {
|
|
const hero = page.hero;
|
|
|
|
if (hero?.type === 'none') {
|
|
return null;
|
|
}
|
|
|
|
const isEditorial = ['blog', 'blog-item'].includes(page.layout);
|
|
const containerClasses = `mx-auto w-[min(calc(100%_-_2rem),76rem)] max-[45rem]:w-[min(calc(100%_-_1.25rem),76rem)]`;
|
|
const eyebrowClasses =
|
|
'mb-5 font-mono text-xs font-bold tracking-[0.12em] text-[#517000] uppercase';
|
|
const titleClasses = `max-w-[15ch] font-sans font-semibold tracking-[-0.065em] leading-[0.98] ${
|
|
hero?.type === 'low'
|
|
? 'text-[clamp(2.4rem,4.7vw,4.5rem)]'
|
|
: hero?.type === 'middle'
|
|
? 'text-[clamp(2.7rem,5.4vw,5.2rem)]'
|
|
: 'text-[clamp(2.75rem,6.2vw,6rem)]'
|
|
}`;
|
|
|
|
if (!hero) {
|
|
return (
|
|
<section className="overflow-hidden border-b border-[#d6d7cf]">
|
|
<div
|
|
className={`${containerClasses} relative z-10 max-w-200 py-[clamp(2.75rem,6vw,5rem)] ${isEditorial ? 'max-w-184' : ''}`}
|
|
>
|
|
<p className={eyebrowClasses}>{page.layout.replace('-', ' ')}</p>
|
|
<h1 className="max-w-[15ch] text-[clamp(2.4rem,4.7vw,4.5rem)] leading-[0.98] font-semibold tracking-[-0.065em]">
|
|
{page.title}
|
|
</h1>
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|
|
|
|
const hasMedia = Boolean(hero.media?.url);
|
|
const impactClasses = {
|
|
low: 'py-[clamp(2.75rem,6vw,5rem)]',
|
|
middle: 'py-[clamp(4rem,8vw,7rem)]',
|
|
high: 'min-h-[min(49rem,calc(100dvh-5rem))] py-[clamp(4rem,9vw,8rem)] max-lg:min-h-0'
|
|
}[hero.type];
|
|
|
|
return (
|
|
<section
|
|
className={`overflow-hidden border-b border-[#d6d7cf] ${
|
|
hero.type === 'high'
|
|
? 'bg-[radial-gradient(circle_at_85%_15%,rgb(199_255_63/23%),transparent_26rem)]'
|
|
: ''
|
|
}`}
|
|
data-hero-impact={hero.type}
|
|
>
|
|
<div
|
|
className={`${containerClasses} grid items-center gap-[clamp(2rem,5vw,5rem)] ${impactClasses} max-[45rem]:py-14 ${
|
|
hasMedia
|
|
? 'grid-cols-[minmax(0,1fr)_minmax(20rem,0.85fr)] max-lg:grid-cols-[minmax(0,1.1fr)_minmax(16rem,0.75fr)] max-[45rem]:grid-cols-1'
|
|
: ''
|
|
}`}
|
|
>
|
|
<div className={`relative z-10 max-w-200 ${isEditorial ? 'max-w-184' : ''}`}>
|
|
<p className={eyebrowClasses}>{page.layout.replace('-', ' ')}</p>
|
|
<h1 className={titleClasses}>{hero.title || page.title}</h1>
|
|
{hero.subtitle ? (
|
|
<p className="mt-6 max-w-152 text-[clamp(1.1rem,2vw,1.35rem)] leading-[1.55] text-[#5d675f]">
|
|
{hero.subtitle}
|
|
</p>
|
|
) : null}
|
|
<RichTextContent
|
|
value={hero.content}
|
|
className={`mt-5 max-w-156 ${isEditorial ? 'max-w-184' : ''}`}
|
|
/>
|
|
<LinkList links={hero.ctaItems} className="mt-8" />
|
|
</div>
|
|
{hasMedia ? (
|
|
<figure className="relative m-0 before:absolute before:-inset-3 before:rotate-2 before:rounded-[2.75rem] before:border before:border-[#172019]/15 before:content-['']">
|
|
<MediaImage
|
|
media={hero.media}
|
|
eager
|
|
className="relative aspect-4/5 rounded-4xl shadow-[0_1.5rem_4rem_rgb(23_32_25/12%)] max-[45rem]:aspect-4/3"
|
|
/>
|
|
</figure>
|
|
) : null}
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|