81 lines
2.6 KiB
TypeScript
81 lines
2.6 KiB
TypeScript
import type { ReactNode } from 'react';
|
|
import Glow, { GridPattern } from '@/components/site/glow';
|
|
import Pill from '@/components/site/pill';
|
|
import Section from '@/components/site/section';
|
|
import { cn } from '@/lib/utils';
|
|
|
|
type PageHeroProps = {
|
|
badge: string;
|
|
title: ReactNode;
|
|
description: ReactNode;
|
|
align?: 'left' | 'center';
|
|
/** Extra content below the lead paragraph (actions, stats, media). */
|
|
children?: ReactNode;
|
|
className?: string;
|
|
};
|
|
|
|
export default function PageHero({
|
|
badge,
|
|
title,
|
|
description,
|
|
align = 'left',
|
|
children,
|
|
className,
|
|
}: PageHeroProps) {
|
|
return (
|
|
<Section
|
|
tone="muted"
|
|
className={className}
|
|
background={
|
|
<>
|
|
<GridPattern />
|
|
<Glow className="-top-40 -left-20 h-[500px] w-[640px]" />
|
|
<Glow className="bg-primary/15 top-1/4 -right-20 h-[480px] w-[520px]" />
|
|
</>
|
|
}
|
|
>
|
|
<div
|
|
className={cn(
|
|
'flex flex-col gap-10',
|
|
align === 'center' && 'items-center text-center',
|
|
)}
|
|
>
|
|
<div
|
|
className={cn(
|
|
'flex max-w-4xl flex-col gap-5',
|
|
align === 'center' && 'items-center',
|
|
)}
|
|
>
|
|
<Pill
|
|
pulse
|
|
className={cn(align === 'center' && 'self-center')}
|
|
>
|
|
{badge}
|
|
</Pill>
|
|
<h1 className="font-display text-on-surface lg:text-display-lg text-4xl leading-[1.12] font-extrabold tracking-tight sm:text-5xl">
|
|
{title}
|
|
</h1>
|
|
<p className="text-on-surface-variant max-w-3xl text-base leading-relaxed lg:text-lg">
|
|
{description}
|
|
</p>
|
|
</div>
|
|
{children}
|
|
</div>
|
|
</Section>
|
|
);
|
|
}
|
|
|
|
/** Crimson gradient emphasis for a phrase inside a hero title. */
|
|
export function Highlight({ children }: { children: ReactNode }) {
|
|
return (
|
|
<span className="from-primary-container via-primary dark:from-primary bg-gradient-to-r to-rose-500 bg-clip-text text-transparent dark:via-rose-300 dark:to-rose-400">
|
|
{children}
|
|
</span>
|
|
);
|
|
}
|
|
|
|
/** Inline emphasis inside body copy. */
|
|
export function Strong({ children }: { children: ReactNode }) {
|
|
return <span className="text-on-surface font-semibold">{children}</span>;
|
|
}
|