Rebuild the About page from the current marketing frames, and leave the unapproved sentences off the page.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
3dee3a587b
commit
2101676429
56 files changed
+1515
-238
No files matched your search
@@ -0,0 +1,26 @@
|
||||
"use client";
|
||||
|
||||
/**
|
||||
* Figma: "Section / Centered Header" (24214:25892)
|
||||
*/
|
||||
|
||||
import { memo } from "react";
|
||||
import { useMessages } from "../../../contexts/MessagesContext";
|
||||
import CenteredHeaderView from "./CenteredHeader.view";
|
||||
import type { CenteredHeaderSegment } from "./CenteredHeader.types";
|
||||
|
||||
const CenteredHeaderContainer = memo(() => {
|
||||
const copy = useMessages().pages.about.centeredHeader;
|
||||
return (
|
||||
<CenteredHeaderView
|
||||
accessibleName={copy.accessibleName}
|
||||
subhead={copy.subhead}
|
||||
credit={copy.credit}
|
||||
segments={copy.segments as CenteredHeaderSegment[]}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
CenteredHeaderContainer.displayName = "CenteredHeader";
|
||||
|
||||
export default CenteredHeaderContainer;
|
||||
@@ -0,0 +1,12 @@
|
||||
export type CenteredHeaderIcon = "arrow" | "ring";
|
||||
|
||||
export type CenteredHeaderSegment =
|
||||
| { type: "word"; text: string }
|
||||
| { type: "icon"; icon: CenteredHeaderIcon };
|
||||
|
||||
export interface CenteredHeaderViewProps {
|
||||
accessibleName: string;
|
||||
segments: CenteredHeaderSegment[];
|
||||
subhead: string;
|
||||
credit: string;
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
"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);
|
||||
@@ -0,0 +1,6 @@
|
||||
export { default } from "./CenteredHeader.container";
|
||||
export type {
|
||||
CenteredHeaderIcon,
|
||||
CenteredHeaderSegment,
|
||||
CenteredHeaderViewProps,
|
||||
} from "./CenteredHeader.types";
|
||||
Reference in new issue
Block a user