Keep space under the guide logo and align header and body.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
adilallo
2026-08-18 21:36:12 -06:00
co-authored by Cursor
parent 73cb73a5af
commit 63842b31c8
7 changed files with 81 additions and 36 deletions
@@ -153,21 +153,17 @@ export default function LegalDocumentPage({
/> />
<div className="relative min-h-screen overflow-x-hidden bg-transparent"> <div className="relative min-h-screen overflow-x-hidden bg-transparent">
<ContentBanner post={post} variant="guide" /> <ContentBanner
post={post}
variant="guide"
updatedLabel={page.updated}
/>
<article <article
className="relative z-10 p-[var(--spacing-scale-024)] sm:py-[var(--spacing-scale-032)]" className="relative z-10 flex w-full justify-center p-[var(--spacing-scale-024)] sm:px-0 sm:py-[var(--spacing-scale-032)]"
data-node-id="19003:23574" data-node-id="19003:23574"
> >
<div className={`${ARTICLE_COLUMN_CLASS} -mt-[var(--spacing-scale-048)]`}> <div className={ARTICLE_COLUMN_CLASS}>
<div
className="flex flex-wrap items-end gap-[var(--measures-spacing-008,8px)] text-xx-small-paragraph text-[var(--color-content-default-secondary)] md:text-x-small-paragraph lg:text-small-paragraph xl:text-large-paragraph"
data-name="Metadata Container"
>
<span>{page.banner.author}</span>
<span>{page.updated}</span>
</div>
{page.intro.length > 0 ? ( {page.intro.length > 0 ? (
<div className="flex flex-col gap-[1em]"> <div className="flex flex-col gap-[1em]">
{page.intro.map((paragraph) => ( {page.intro.map((paragraph) => (
+1 -1
View File
@@ -111,7 +111,7 @@ export default function HowItWorksPage() {
<article className="relative z-10 p-[var(--spacing-scale-024)] sm:py-[var(--spacing-scale-032)]"> <article className="relative z-10 p-[var(--spacing-scale-024)] sm:py-[var(--spacing-scale-032)]">
<div <div
className="post-body -mt-[var(--spacing-scale-048)] text-[var(--color-content-default-primary)] text-medium-paragraph sm:text-large-paragraph lg:text-x-large-paragraph xl:text-xx-large-paragraph sm:mx-auto sm:max-w-[390px] md:max-w-[472px] lg:max-w-[700px] xl:max-w-[904px]" className="post-body text-[var(--color-content-default-primary)] text-medium-paragraph sm:text-large-paragraph lg:text-x-large-paragraph xl:text-xx-large-paragraph sm:mx-auto sm:max-w-[390px] md:max-w-[472px] lg:max-w-[700px] xl:max-w-[904px]"
dangerouslySetInnerHTML={{ __html: syntheticPost.htmlContent }} dangerouslySetInnerHTML={{ __html: syntheticPost.htmlContent }}
/> />
</article> </article>
@@ -22,6 +22,7 @@ const ContentBannerContainer = memo<ContentBannerProps>(
leadingImageAlt, leadingImageAlt,
rulePreview, rulePreview,
contentTone, contentTone,
updatedLabel,
}) => { }) => {
const variant = variantProp; const variant = variantProp;
const tUseCase = useTranslation("pages.useCasesCompletedRule"); const tUseCase = useTranslation("pages.useCasesCompletedRule");
@@ -81,6 +82,7 @@ const ContentBannerContainer = memo<ContentBannerProps>(
rulePreview={rulePreview} rulePreview={rulePreview}
contentTone={contentTone} contentTone={contentTone}
ruleCardLinkAriaLabel={ruleCardLinkAriaLabel} ruleCardLinkAriaLabel={ruleCardLinkAriaLabel}
updatedLabel={updatedLabel}
/> />
); );
}, },
@@ -28,6 +28,8 @@ export interface ContentBannerProps {
rulePreview?: ContentBannerRulePreview; rulePreview?: ContentBannerRulePreview;
/** `useCase` only: ContentContainer text tokens (default `onLight`). */ /** `useCase` only: ContentContainer text tokens (default `onLight`). */
contentTone?: ContentContainerToneValue; contentTone?: ContentContainerToneValue;
/** `guide` only: author + this label under the title. */
updatedLabel?: string;
} }
export interface ContentBannerViewProps { export interface ContentBannerViewProps {
@@ -43,4 +45,6 @@ export interface ContentBannerViewProps {
contentTone?: ContentContainerToneValue; contentTone?: ContentContainerToneValue;
/** `useCase` only: aria-label for linked rule preview. */ /** `useCase` only: aria-label for linked rule preview. */
ruleCardLinkAriaLabel?: string; ruleCardLinkAriaLabel?: string;
/** `guide` only: attribution row under the title. */
updatedLabel?: string;
} }
@@ -17,23 +17,23 @@ import type { ContentBannerViewProps } from "./ContentBanner.types";
*/ */
function ContentBannerGuideView({ function ContentBannerGuideView({
post, post,
}: Pick<ContentBannerViewProps, "post">) { updatedLabel,
const { title, description } = post.frontmatter; }: Pick<ContentBannerViewProps, "post" | "updatedLabel">) {
const { title, description, author } = post.frontmatter;
return ( return (
<section <section
className="relative w-full overflow-clip px-[var(--spacing-scale-020)] py-[var(--spacing-scale-024)] sm:px-[var(--spacing-scale-032)] sm:py-[var(--spacing-scale-032)] lg:px-[var(--spacing-scale-048)] lg:py-[var(--spacing-scale-040)]" className="relative w-full overflow-clip px-[var(--spacing-scale-020)] py-[var(--spacing-scale-024)] sm:px-[var(--spacing-scale-032)] sm:py-[var(--spacing-scale-032)] lg:px-[var(--spacing-scale-048)] lg:py-[var(--spacing-scale-040)] xl:px-[var(--spacing-scale-064)] xl:py-[var(--spacing-scale-076)]"
aria-labelledby="content-banner-title" aria-labelledby="content-banner-title"
> >
<div <div
className="mx-auto flex w-full max-w-[1024px] flex-col items-start gap-[var(--spacing-scale-024)] md:flex-row md:items-center md:gap-[var(--spacing-scale-032)]" className="mx-auto flex w-full max-w-[1024px] flex-col items-start gap-[var(--spacing-scale-024)] md:flex-row md:items-start md:gap-[var(--spacing-scale-024)] lg:items-center lg:gap-[var(--spacing-scale-032)] xl:max-w-[1312px] xl:gap-[var(--spacing-scale-056)]"
data-node-id="19189:9358" data-node-id="19189:9358"
> >
<div <div
className="flex w-full max-w-[365px] shrink-0 flex-col items-start justify-center gap-[var(--spacing-scale-024)]" className="flex w-full shrink-0 flex-col items-start justify-center gap-[var(--measures-spacing-016)] md:max-w-[280px] lg:max-w-[365px] xl:max-w-[623px]"
data-node-id="19189:9171" data-node-id="19189:9171"
> >
<div className="flex w-full flex-col items-start gap-[var(--measures-spacing-016)]">
<div className="flex w-full flex-col items-start gap-[var(--measures-spacing-004)] text-left text-[var(--color-content-default-primary)]"> <div className="flex w-full flex-col items-start gap-[var(--measures-spacing-004)] text-left text-[var(--color-content-default-primary)]">
<h1 <h1
id="content-banner-title" id="content-banner-title"
@@ -47,11 +47,19 @@ function ContentBannerGuideView({
</p> </p>
) : null} ) : null}
</div> </div>
{updatedLabel ? (
<div
className="flex w-full flex-wrap items-end gap-[var(--measures-spacing-008,8px)] text-xx-small-paragraph text-[var(--color-content-default-secondary)] md:text-x-small-paragraph lg:text-small-paragraph xl:text-large-paragraph"
data-name="Metadata Container"
>
<span>{author}</span>
<span>{updatedLabel}</span>
</div> </div>
) : null}
</div> </div>
<div <div
className="flex w-full shrink-0 items-center justify-center md:flex-1" className="flex w-full shrink-0 items-center justify-center max-sm:pb-[var(--spacing-scale-024)] md:flex-1 md:justify-end"
data-node-id="22078:806960" data-node-id="22078:806960"
> >
{/* eslint-disable-next-line @next/next/no-img-element */} {/* eslint-disable-next-line @next/next/no-img-element */}
@@ -253,7 +261,7 @@ function ContentBannerUseCaseView({
function ContentBannerView(props: ContentBannerViewProps) { function ContentBannerView(props: ContentBannerViewProps) {
if (props.variant === "guide") { if (props.variant === "guide") {
return <ContentBannerGuideView post={props.post} />; return <ContentBannerGuideView post={props.post} updatedLabel={props.updatedLabel} />;
} }
if (props.variant === "useCase") { if (props.variant === "useCase") {
+31 -2
View File
@@ -179,15 +179,44 @@ describe("ContentBanner", () => {
expect(screen.getByText("Test description")).toBeInTheDocument(); expect(screen.getByText("Test description")).toBeInTheDocument();
expect(screen.queryByText("Test Author")).not.toBeInTheDocument(); expect(screen.queryByText("Test Author")).not.toBeInTheDocument();
const copyColumn = container.querySelector('[data-node-id="19189:9171"]');
expect(copyColumn).toHaveClass(
"md:max-w-[280px]",
"lg:max-w-[365px]",
"xl:max-w-[623px]",
);
expect(copyColumn).not.toHaveClass("max-w-[365px]");
const bannerRow = container.querySelector('[data-node-id="19189:9358"]'); const bannerRow = container.querySelector('[data-node-id="19189:9358"]');
expect(bannerRow).toHaveClass("md:flex-row"); expect(bannerRow).toHaveClass("md:flex-row");
expect(bannerRow?.className).toMatch(/xl:max-w-\[1312px\]/);
const logoMark = container.querySelector( const logoMarkWrap = container.querySelector(
'[data-node-id="22078:806960"] img', '[data-node-id="22078:806960"]',
); );
expect(logoMarkWrap?.className).toMatch(
/max-sm:pb-\[var\(--spacing-scale-024\)\]/,
);
expect(logoMarkWrap).toHaveClass("md:justify-end");
const logoMark = logoMarkWrap?.querySelector("img");
expect(logoMark).toHaveAttribute( expect(logoMark).toHaveAttribute(
"src", "src",
expect.stringContaining("guide-banner-logo-arrow.svg"), expect.stringContaining("guide-banner-logo-arrow.svg"),
); );
}); });
it("renders guide metadata under the title when updatedLabel is set", () => {
render(
<ContentBanner
post={mockPost}
variant="guide"
updatedLabel="Last updated August 15, 2026."
/>,
);
expect(screen.getByText("Test Author")).toBeInTheDocument();
expect(
screen.getByText("Last updated August 15, 2026."),
).toBeInTheDocument();
});
}); });
+7 -1
View File
@@ -7,10 +7,16 @@ import CookiesPage from "../../app/(marketing)/cookies/page";
import messages from "../../messages/en/index"; import messages from "../../messages/en/index";
vi.mock("../../app/components/sections/ContentBanner", () => ({ vi.mock("../../app/components/sections/ContentBanner", () => ({
default: ({ post, variant }) => ( default: ({ post, variant, updatedLabel }) => (
<section data-testid="content-banner" data-variant={variant}> <section data-testid="content-banner" data-variant={variant}>
<h1>{post.frontmatter.title}</h1> <h1>{post.frontmatter.title}</h1>
<p>{post.frontmatter.description}</p> <p>{post.frontmatter.description}</p>
{updatedLabel ? (
<div>
<span>{post.frontmatter.author}</span>
<span>{updatedLabel}</span>
</div>
) : null}
</section> </section>
), ),
})); }));