Match the marketing homepage, About page, and folder header to the latest Figma #74

Merged
an.di merged 3 commits from adilallo/fix/CR-173-home-about-feature-grid into main 2026-09-10 03:41:44 +00:00
9 changed files with 31 additions and 9 deletions
Showing only changes of commit b42716c262 - Show all commits
@@ -1,6 +1,7 @@
"use client"; "use client";
import { memo } from "react"; import { memo } from "react";
import NextLink from "next/link";
import Button from "../../buttons/Button"; import Button from "../../buttons/Button";
import { contentLockupShapePath, getAssetPath } from "../../../../lib/assetUtils"; import { contentLockupShapePath, getAssetPath } from "../../../../lib/assetUtils";
import type { ContentLockupViewProps } from "./ContentLockup.types"; import type { ContentLockupViewProps } from "./ContentLockup.types";
@@ -98,14 +99,13 @@ function ContentLockupView({
</div> </div>
)} )}
{/* Link for feature variant */}
{variant === "feature" && linkText && linkHref && ( {variant === "feature" && linkText && linkHref && (
<a <NextLink
href={linkHref} href={linkHref}
className="text-medium-underline underline text-[var(--color-content-default-primary)] hover:text-[var(--color-content-default-secondary)] transition-colors focus:outline-none focus:ring-2 focus:ring-[var(--color-surface-default-brand-royal)] focus:ring-offset-2 focus:ring-offset-[var(--color-surface-default-secondary)] rounded-sm px-1 py-0.5" className="w-fit self-start cursor-pointer text-small-paragraph md:text-medium-paragraph text-[var(--color-content-default-primary)] underline decoration-solid [text-underline-position:from-font] hover:opacity-90 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--color-border-invert-primary)]"
> >
{linkText} {linkText}
</a> </NextLink>
)} )}
{/* CTA Button */} {/* CTA Button */}
+4 -3
View File
@@ -8,7 +8,7 @@ Convention for files served from `public/`. Path helpers live in
``` ```
public/ public/
assets/ assets/
icons/ # UI chrome (alert, close, help, pointer) icons/ # UI chrome (close, help) + FeatureGrid card glyphs
logos/ # Brand + social lockups logos/ # Brand + social lockups
partners/ # Logo wall partner SVGs (kebab org slug) partners/ # Logo wall partner SVGs (kebab org slug)
marketing/ # Hero, feature panels, section numbers, avatars, banners, book cover marketing/ # Hero, feature panels, section numbers, avatars, banners, book cover
@@ -25,7 +25,7 @@ public/
| Location | Used for | Resolution | | Location | Used for | Resolution |
| --- | --- | --- | | --- | --- | --- |
| `public/assets/icons/` | Static chrome served by URL (`icon-close.svg`, `icon-help.svg`) | `ASSETS.ICON_*` | | `public/assets/icons/` | Static chrome served by URL (`icon-close.svg`, `icon-help.svg`) and FeatureGrid card glyphs (`icon-git-branch.svg`, …) | `ASSETS.ICON_*`, `featureIconPath()` |
| `app/components/asset/icon/` | Bundled create-flow / nav SVGs imported by `Icon.tsx` | Webpack import, not `public/` | | `app/components/asset/icon/` | Bundled create-flow / nav SVGs imported by `Icon.tsx` | Webpack import, not `public/` |
Do not duplicate the same glyph in both places unless migrating between systems. Do not duplicate the same glyph in both places unless migrating between systems.
@@ -61,7 +61,8 @@ stage. Raster → SVG conversion is tracked in
| Path | Used by | Disposition | | Path | Used by | Disposition |
| --- | --- | --- | | --- | --- | --- |
| `logos/partners/*.svg` (×6) | LogoWall | **Done** — SVG (kebab org slug, no `logo-` prefix) | | `logos/partners/*.svg` (×6) | LogoWall | **Done** — SVG (kebab org slug, no `logo-` prefix) |
| `marketing/feature-*.svg` (×4) | FeatureGrid | Exported from Figma Section/Feature-Grid (18847:22410) | | `marketing/feature-*.svg` (×4) | Mini cards | Panel art (`support`, `exercises`, `guidance`, `tools`) |
| `icons/icon-{git-branch,arrow-left-right,door-open,message-square-share}.svg` | FeatureGrid | Card glyphs from Figma Section/Feature-Grid (18632:10668) |
| `marketing/section-number-*.svg` (×3) | SectionNumber | **Done** — SVG | | `marketing/section-number-*.svg` (×3) | SectionNumber | **Done** — SVG |
| `marketing/avatar-*.svg` (×3) | Avatar / ASSETS | **Done** — SVG | | `marketing/avatar-*.svg` (×3) | Avatar / ASSETS | **Done** — SVG |
| `marketing/hero-image.png` | HeroBanner | **Design review** — likely keep raster | | `marketing/hero-image.png` | HeroBanner | **Design review** — likely keep raster |
+2 -2
View File
@@ -114,7 +114,7 @@ export function featurePanelPath(key: FeaturePanelKey): string {
return `assets/marketing/feature-${key}.svg`; return `assets/marketing/feature-${key}.svg`;
} }
/** Feature-grid card glyphs (Figma **18632:10668**). */ /** Feature-grid card glyphs in `public/assets/icons/` (Figma **18632:10668**). */
export type FeatureIconKey = export type FeatureIconKey =
| "git-branch" | "git-branch"
| "arrow-left-right" | "arrow-left-right"
@@ -122,7 +122,7 @@ export type FeatureIconKey =
| "message-square-share"; | "message-square-share";
export function featureIconPath(key: FeatureIconKey): string { export function featureIconPath(key: FeatureIconKey): string {
return `assets/marketing/feature-icon-${key}.svg`; return `assets/icons/icon-${key}.svg`;
} }
/** Case study card artwork in `public/assets/case-study/`. */ /** Case study card artwork in `public/assets/case-study/`. */

Before

Width:  |  Height:  |  Size: 406 B

After

Width:  |  Height:  |  Size: 406 B

Before

Width:  |  Height:  |  Size: 1018 B

After

Width:  |  Height:  |  Size: 1018 B

Before

Width:  |  Height:  |  Size: 602 B

After

Width:  |  Height:  |  Size: 602 B

Before

Width:  |  Height:  |  Size: 800 B

After

Width:  |  Height:  |  Size: 800 B

+1
View File
@@ -132,6 +132,7 @@ describe("FeatureGrid (behavioral tests)", () => {
expect(icon).toHaveAttribute("width", "40"); expect(icon).toHaveAttribute("width", "40");
expect(icon).toHaveAttribute("height", "40"); expect(icon).toHaveAttribute("height", "40");
expect(icon).toHaveAttribute("alt", ""); expect(icon).toHaveAttribute("alt", "");
expect(icon.getAttribute("src")).toMatch(/^\/assets\/icons\/icon-/);
}); });
}); });
}); });
@@ -63,4 +63,24 @@ describe("ContentLockup", () => {
expect(description.className).toContain("text-small-paragraph"); expect(description.className).toContain("text-small-paragraph");
expect(description.className).toContain("sm:text-large-paragraph"); expect(description.className).toContain("sm:text-large-paragraph");
}); });
it("renders the feature lockup CTA as an inline text link", () => {
renderWithProviders(
<ContentLockup
variant="feature"
title="Tools for the parts that get hard"
subtitle="Every group runs into the same knots."
linkText="Explore the toolkit"
linkHref="/learn"
/>,
);
const link = screen.getByRole("link", { name: "Explore the toolkit" });
expect(link).toHaveAttribute("href", "/learn");
expect(link.className).toMatch(/underline/);
expect(link.className).toMatch(/w-fit/);
expect(link.className).not.toMatch(/px-1/);
expect(link.className).not.toMatch(/focus:ring-2/);
expect(link.className).toMatch(/focus-visible:outline/);
});
}); });