diff --git a/app/components/type/ContentLockup/ContentLockup.view.tsx b/app/components/type/ContentLockup/ContentLockup.view.tsx index 0707a97..47ad212 100644 --- a/app/components/type/ContentLockup/ContentLockup.view.tsx +++ b/app/components/type/ContentLockup/ContentLockup.view.tsx @@ -1,6 +1,7 @@ "use client"; import { memo } from "react"; +import NextLink from "next/link"; import Button from "../../buttons/Button"; import { contentLockupShapePath, getAssetPath } from "../../../../lib/assetUtils"; import type { ContentLockupViewProps } from "./ContentLockup.types"; @@ -98,14 +99,13 @@ function ContentLockupView({ )} - {/* Link for feature variant */} {variant === "feature" && linkText && linkHref && ( - {linkText} - + )} {/* CTA Button */} diff --git a/docs/guides/static-assets.md b/docs/guides/static-assets.md index 22c2c19..46313e1 100644 --- a/docs/guides/static-assets.md +++ b/docs/guides/static-assets.md @@ -8,7 +8,7 @@ Convention for files served from `public/`. Path helpers live in ``` public/ assets/ - icons/ # UI chrome (alert, close, help, pointer) + icons/ # UI chrome (close, help) + FeatureGrid card glyphs logos/ # Brand + social lockups partners/ # Logo wall partner SVGs (kebab org slug) marketing/ # Hero, feature panels, section numbers, avatars, banners, book cover @@ -25,7 +25,7 @@ public/ | 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/` | 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 | | --- | --- | --- | | `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/avatar-*.svg` (×3) | Avatar / ASSETS | **Done** — SVG | | `marketing/hero-image.png` | HeroBanner | **Design review** — likely keep raster | diff --git a/lib/assetUtils.ts b/lib/assetUtils.ts index 3661369..1be1024 100644 --- a/lib/assetUtils.ts +++ b/lib/assetUtils.ts @@ -114,7 +114,7 @@ export function featurePanelPath(key: FeaturePanelKey): string { 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 = | "git-branch" | "arrow-left-right" @@ -122,7 +122,7 @@ export type FeatureIconKey = | "message-square-share"; 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/`. */ diff --git a/public/assets/marketing/feature-icon-arrow-left-right.svg b/public/assets/icons/icon-arrow-left-right.svg similarity index 100% rename from public/assets/marketing/feature-icon-arrow-left-right.svg rename to public/assets/icons/icon-arrow-left-right.svg diff --git a/public/assets/marketing/feature-icon-door-open.svg b/public/assets/icons/icon-door-open.svg similarity index 100% rename from public/assets/marketing/feature-icon-door-open.svg rename to public/assets/icons/icon-door-open.svg diff --git a/public/assets/marketing/feature-icon-git-branch.svg b/public/assets/icons/icon-git-branch.svg similarity index 100% rename from public/assets/marketing/feature-icon-git-branch.svg rename to public/assets/icons/icon-git-branch.svg diff --git a/public/assets/marketing/feature-icon-message-square-share.svg b/public/assets/icons/icon-message-square-share.svg similarity index 100% rename from public/assets/marketing/feature-icon-message-square-share.svg rename to public/assets/icons/icon-message-square-share.svg diff --git a/tests/components/FeatureGrid.test.tsx b/tests/components/FeatureGrid.test.tsx index 6400edc..c5570a8 100644 --- a/tests/components/FeatureGrid.test.tsx +++ b/tests/components/FeatureGrid.test.tsx @@ -132,6 +132,7 @@ describe("FeatureGrid (behavioral tests)", () => { expect(icon).toHaveAttribute("width", "40"); expect(icon).toHaveAttribute("height", "40"); expect(icon).toHaveAttribute("alt", ""); + expect(icon.getAttribute("src")).toMatch(/^\/assets\/icons\/icon-/); }); }); }); diff --git a/tests/components/type/ContentLockup.test.tsx b/tests/components/type/ContentLockup.test.tsx index d5f0b7b..d99ecb9 100644 --- a/tests/components/type/ContentLockup.test.tsx +++ b/tests/components/type/ContentLockup.test.tsx @@ -63,4 +63,24 @@ describe("ContentLockup", () => { expect(description.className).toContain("text-small-paragraph"); expect(description.className).toContain("sm:text-large-paragraph"); }); + + it("renders the feature lockup CTA as an inline text link", () => { + renderWithProviders( + , + ); + + 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/); + }); });