-
- {page.banner.author}
- {page.updated}
-
-
+
{page.intro.length > 0 ? (
{page.intro.map((paragraph) => (
diff --git a/app/(marketing)/how-it-works/page.tsx b/app/(marketing)/how-it-works/page.tsx
index 7a88575..9d2696c 100644
--- a/app/(marketing)/how-it-works/page.tsx
+++ b/app/(marketing)/how-it-works/page.tsx
@@ -111,7 +111,7 @@ export default function HowItWorksPage() {
diff --git a/app/components/sections/ContentBanner/ContentBanner.container.tsx b/app/components/sections/ContentBanner/ContentBanner.container.tsx
index 6b77cc7..54b74ae 100644
--- a/app/components/sections/ContentBanner/ContentBanner.container.tsx
+++ b/app/components/sections/ContentBanner/ContentBanner.container.tsx
@@ -22,6 +22,7 @@ const ContentBannerContainer = memo(
leadingImageAlt,
rulePreview,
contentTone,
+ updatedLabel,
}) => {
const variant = variantProp;
const tUseCase = useTranslation("pages.useCasesCompletedRule");
@@ -81,6 +82,7 @@ const ContentBannerContainer = memo(
rulePreview={rulePreview}
contentTone={contentTone}
ruleCardLinkAriaLabel={ruleCardLinkAriaLabel}
+ updatedLabel={updatedLabel}
/>
);
},
diff --git a/app/components/sections/ContentBanner/ContentBanner.types.ts b/app/components/sections/ContentBanner/ContentBanner.types.ts
index eeb3c4d..5ced348 100644
--- a/app/components/sections/ContentBanner/ContentBanner.types.ts
+++ b/app/components/sections/ContentBanner/ContentBanner.types.ts
@@ -28,6 +28,8 @@ export interface ContentBannerProps {
rulePreview?: ContentBannerRulePreview;
/** `useCase` only: ContentContainer text tokens (default `onLight`). */
contentTone?: ContentContainerToneValue;
+ /** `guide` only: author + this label under the title. */
+ updatedLabel?: string;
}
export interface ContentBannerViewProps {
@@ -43,4 +45,6 @@ export interface ContentBannerViewProps {
contentTone?: ContentContainerToneValue;
/** `useCase` only: aria-label for linked rule preview. */
ruleCardLinkAriaLabel?: string;
+ /** `guide` only: attribution row under the title. */
+ updatedLabel?: string;
}
diff --git a/app/components/sections/ContentBanner/ContentBanner.view.tsx b/app/components/sections/ContentBanner/ContentBanner.view.tsx
index 095b034..79e6d19 100644
--- a/app/components/sections/ContentBanner/ContentBanner.view.tsx
+++ b/app/components/sections/ContentBanner/ContentBanner.view.tsx
@@ -17,41 +17,49 @@ import type { ContentBannerViewProps } from "./ContentBanner.types";
*/
function ContentBannerGuideView({
post,
-}: Pick) {
- const { title, description } = post.frontmatter;
+ updatedLabel,
+}: Pick) {
+ const { title, description, author } = post.frontmatter;
return (
-
-
-
+ - {title} -
- {description ? ( -- {description} -
- ) : null} -
+
+ {updatedLabel ? (
+ + {title} +
+ {description ? ( ++ {description} +
+ ) : null}
+ {author}
+ {updatedLabel}
+
+ ) : null}
{/* eslint-disable-next-line @next/next/no-img-element */}
@@ -253,7 +261,7 @@ function ContentBannerUseCaseView({
function ContentBannerView(props: ContentBannerViewProps) {
if (props.variant === "guide") {
- return ;
+ return ;
}
if (props.variant === "useCase") {
diff --git a/tests/components/ContentBanner.test.tsx b/tests/components/ContentBanner.test.tsx
index b7df100..bb3f62b 100644
--- a/tests/components/ContentBanner.test.tsx
+++ b/tests/components/ContentBanner.test.tsx
@@ -179,15 +179,44 @@ describe("ContentBanner", () => {
expect(screen.getByText("Test description")).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"]');
expect(bannerRow).toHaveClass("md:flex-row");
+ expect(bannerRow?.className).toMatch(/xl:max-w-\[1312px\]/);
- const logoMark = container.querySelector(
- '[data-node-id="22078:806960"] img',
+ const logoMarkWrap = container.querySelector(
+ '[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(
"src",
expect.stringContaining("guide-banner-logo-arrow.svg"),
);
});
+
+ it("renders guide metadata under the title when updatedLabel is set", () => {
+ render(
+ ,
+ );
+
+ expect(screen.getByText("Test Author")).toBeInTheDocument();
+ expect(
+ screen.getByText("Last updated August 15, 2026."),
+ ).toBeInTheDocument();
+ });
});
diff --git a/tests/pages/legal.test.tsx b/tests/pages/legal.test.tsx
index 24db6fc..678d6ad 100644
--- a/tests/pages/legal.test.tsx
+++ b/tests/pages/legal.test.tsx
@@ -7,10 +7,16 @@ import CookiesPage from "../../app/(marketing)/cookies/page";
import messages from "../../messages/en/index";
vi.mock("../../app/components/sections/ContentBanner", () => ({
- default: ({ post, variant }) => (
+ default: ({ post, variant, updatedLabel }) => (
),
}));
{post.frontmatter.title}
{post.frontmatter.description}
+ {updatedLabel ? ( +
+ {post.frontmatter.author}
+ {updatedLabel}
+
+ ) : null}