diff --git a/.gitignore b/.gitignore index bf17aa0..337e8a4 100644 --- a/.gitignore +++ b/.gitignore @@ -44,6 +44,9 @@ npm-cache/ !public/favicon-32x32.png !public/apple-touch-icon.png +# Per-article body ornaments (Figma Content page Template image fills) +!public/content/blog/*-ornament-*.png + # Visual regression snapshots (allow these) !tests/e2e/visual-regression.spec.ts-snapshots/ !tests/e2e/visual-regression.spec.ts-snapshots/*.png diff --git a/app/(marketing)/_components/ContentTemplateDecorativeShapes.tsx b/app/(marketing)/_components/ContentTemplateDecorativeShapes.tsx index f0afa00..c06eaa9 100644 --- a/app/(marketing)/_components/ContentTemplateDecorativeShapes.tsx +++ b/app/(marketing)/_components/ContentTemplateDecorativeShapes.tsx @@ -7,16 +7,17 @@ * - 19003:23576 / 19000:23009 — left */ import { - ASSETS, getAssetPath, howItWorksOrnamentLeftPath, howItWorksOrnamentRightPath, + resolveArticleOrnamentPath, } from "../../../lib/assetUtils"; type ContentTemplateDecorativeShapesVariant = "guide" | "article"; type ContentTemplateDecorativeShapesProps = { variant: ContentTemplateDecorativeShapesVariant; + slug?: string; }; const RIGHT_GUIDE_CLASS = @@ -30,8 +31,15 @@ const LEFT_ARTICLE_CLASS = export default function ContentTemplateDecorativeShapes({ variant, + slug, }: ContentTemplateDecorativeShapesProps) { const isArticle = variant === "article"; + const rightSrc = isArticle + ? resolveArticleOrnamentPath(slug, "right") + : getAssetPath(howItWorksOrnamentRightPath()); + const leftSrc = isArticle + ? resolveArticleOrnamentPath(slug, "left") + : getAssetPath(howItWorksOrnamentLeftPath()); return ( <> @@ -42,11 +50,7 @@ export default function ContentTemplateDecorativeShapes({ > {/* eslint-disable-next-line @next/next/no-img-element */} @@ -58,11 +62,7 @@ export default function ContentTemplateDecorativeShapes({ > {/* eslint-disable-next-line @next/next/no-img-element */} diff --git a/app/(marketing)/blog/[slug]/page.tsx b/app/(marketing)/blog/[slug]/page.tsx index 210bd55..6735c88 100644 --- a/app/(marketing)/blog/[slug]/page.tsx +++ b/app/(marketing)/blog/[slug]/page.tsx @@ -208,7 +208,10 @@ export default async function BlogPostPage({ params }: PageProps) {
- +
{ expect(shapes[1]).toHaveClass("object-contain"); }); + it("uses per-article body ornaments for catalog posts", async () => { + const { getBlogPostBySlug } = await import("../../lib/content"); + vi.mocked(getBlogPostBySlug).mockReturnValue({ + ...mockPost, + slug: "resolving-active-conflicts", + }); + + const BlogPostPageComponent = await BlogPostPage({ + params: { slug: "resolving-active-conflicts" }, + }); + render(BlogPostPageComponent); + + const shapes = screen.getAllByAltText(""); + expect(shapes[0]).toHaveAttribute( + "src", + "/content/blog/resolving-active-conflicts-ornament-right.png", + ); + expect(shapes[1]).toHaveAttribute( + "src", + "/content/blog/resolving-active-conflicts-ornament-left.png", + ); + }); + it("applies correct styling to article content", async () => { const BlogPostPageComponent = await BlogPostPage({ params: { slug: "test-article" },