Files
community-rule/app/components/sections/CenteredHeader/CenteredHeader.view.tsx
T

104 lines
3.2 KiB
TypeScript

"use client";
import { memo, type ReactNode } from "react";
import { getAssetPath } from "../../../../lib/assetUtils";
import type {
CenteredHeaderIcon,
CenteredHeaderSegment,
CenteredHeaderViewProps,
} from "./CenteredHeader.types";
const ICON_SRC: Record<CenteredHeaderIcon, string> = {
arrow: "assets/shapes/about-header-arrow.svg",
ring: "assets/shapes/about-header-ring.svg",
};
const ICON_CLASS: Record<CenteredHeaderIcon, string> = {
arrow: "size-10 md:size-[54px] lg:size-20",
ring: "size-8 md:size-[54px] lg:size-20",
};
/** Poster lines at 1024+, matching the desktop frame. Narrower widths wrap on their own. */
const DESKTOP_LINES = [[0], [1], [2, 3], [4, 5], [6, 7, 8]] as const;
function SegmentView({ segment }: { segment: CenteredHeaderSegment }) {
if (segment.type === "word") {
return (
<span className="font-bricolage-grotesque text-display-m whitespace-nowrap text-[var(--color-content-default-primary)] md:text-display-xl lg:text-display-xxl">
{segment.text}
</span>
);
}
return (
<span
className={`inline-flex shrink-0 items-center justify-center ${ICON_CLASS[segment.icon]}`}
>
{/* eslint-disable-next-line @next/next/no-img-element -- decorative Figma mark */}
<img
src={getAssetPath(ICON_SRC[segment.icon])}
alt=""
width={80}
height={80}
className="size-full"
/>
</span>
);
}
function CenteredHeaderView({
accessibleName,
segments,
subhead,
credit,
}: CenteredHeaderViewProps) {
const desktopLines: ReactNode = DESKTOP_LINES.map((line) => (
<div key={line.join("-")} className="flex items-center justify-center gap-4">
{line.map((index) => {
const segment = segments[index];
return segment ? <SegmentView key={index} segment={segment} /> : null;
})}
</div>
));
return (
<section
data-figma-node="24214:25892"
className="flex flex-col items-center gap-[var(--space-600)] overflow-hidden bg-black px-[var(--space-600)] py-[var(--space-3000)] md:px-[var(--space-1800)]"
aria-labelledby="about-centered-header"
>
<h1 id="about-centered-header" className="sr-only">
{accessibleName}
</h1>
<div
aria-hidden
className="flex w-full flex-wrap items-center justify-center gap-x-3 gap-y-2 lg:hidden"
>
{segments.map((segment, index) => (
<SegmentView key={index} segment={segment} />
))}
</div>
<div
aria-hidden
className="hidden w-full max-w-[32rem] flex-col items-center gap-4 lg:flex"
>
{desktopLines}
</div>
<p className="max-w-[720px] text-center font-inter text-paragraph-m text-[var(--color-content-default-secondary)] md:text-paragraph-xl lg:font-bricolage-grotesque lg:text-display-s">
{subhead}
</p>
<div
className="h-px w-[295px] bg-[var(--color-border-default-secondary)]"
aria-hidden
/>
<p className="max-w-[720px] text-center font-inter text-label-xs text-[var(--color-content-default-tertiary)] md:text-label-s">
{credit}
</p>
</section>
);
}
CenteredHeaderView.displayName = "CenteredHeaderView";
export default memo(CenteredHeaderView);