From 466a02a246d5a16788e92c4b7282ec68f681f6e6 Mon Sep 17 00:00:00 2001 From: Rodrigo Opalo Balog Date: Tue, 4 Aug 2026 12:08:08 -0400 Subject: [PATCH 1/2] feat(portfolio): implement compact editorial card rows --- src/Components/portfolio/PortfolioCard.tsx | 20 +++++++++----------- src/pages/PortfolioPage.tsx | 1 - 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/src/Components/portfolio/PortfolioCard.tsx b/src/Components/portfolio/PortfolioCard.tsx index 888e86d..6328bbb 100644 --- a/src/Components/portfolio/PortfolioCard.tsx +++ b/src/Components/portfolio/PortfolioCard.tsx @@ -71,7 +71,6 @@ interface PortfolioCardProps { cover: string; desc: string; details: ReactNode; - expanded: boolean; headingLevel?: "h2" | "h3"; disclaimer?: string; priority?: boolean; @@ -86,7 +85,6 @@ export default function PortfolioCard({ cover, desc, details, - expanded, headingLevel = "h3", disclaimer, priority = false, @@ -101,32 +99,32 @@ export default function PortfolioCard({ return ( -
-
-
+
+
+
-
+
{status && ( -

+

{status}

)} @@ -140,7 +138,7 @@ export default function PortfolioCard({

)}

• {tags}

-
+
{actions}
{details} diff --git a/src/pages/PortfolioPage.tsx b/src/pages/PortfolioPage.tsx index 85f1a39..1be975d 100644 --- a/src/pages/PortfolioPage.tsx +++ b/src/pages/PortfolioPage.tsx @@ -185,7 +185,6 @@ export default function PortfolioPage() { /> ) : null } - expanded={detailsExpanded} headingLevel="h2" priority={portfolioIndex === 0} tags={content.tags.join(" · ")} From 32a24d4ab793160a59252b2de87c87b2e6a8ce0b Mon Sep 17 00:00:00 2001 From: Rodrigo Opalo Balog Date: Tue, 4 Aug 2026 12:09:13 -0400 Subject: [PATCH 2/2] test(portfolio): lock responsive card system contracts --- src/test/NoJsVisibility.test.tsx | 2 +- src/test/PortfolioSafety.test.ts | 41 ++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/src/test/NoJsVisibility.test.tsx b/src/test/NoJsVisibility.test.tsx index 7c3f0d8..21fa14d 100644 --- a/src/test/NoJsVisibility.test.tsx +++ b/src/test/NoJsVisibility.test.tsx @@ -84,7 +84,7 @@ const approvedFiles = { }, "src/Components/portfolio/PortfolioCard.tsx": { baselineHash: - "82db7710efc1da9799d2b53bc96eb15009f3f5da39aee86f84e3bec56983ecf8", + "88eabddb08798b1e6d638a6a7cde97c36afd61dfb32c595fce627894b333e47d", markers: 1, }, } as const; diff --git a/src/test/PortfolioSafety.test.ts b/src/test/PortfolioSafety.test.ts index fa3d2a1..1359fd3 100644 --- a/src/test/PortfolioSafety.test.ts +++ b/src/test/PortfolioSafety.test.ts @@ -826,4 +826,45 @@ describe("portfolio architecture invariants", () => { expect(faqSource).not.toContain("techAnswer"); expect(faqSource).not.toMatch(/questions\[\d+\]/); }); + + it("locks the compact editorial row contract without rigid card heights", () => { + const portfolioCardSource = fs.readFileSync( + path.join( + projectRoot, + "src/Components/portfolio/PortfolioCard.tsx", + ), + "utf8", + ); + const portfolioPageSource = fs.readFileSync( + path.join(projectRoot, "src/pages/PortfolioPage.tsx"), + "utf8", + ); + + expect(portfolioCardSource).toContain( + 'className="flex flex-col lg:flex-row"', + ); + expect(portfolioCardSource).not.toContain("md:flex-row"); + expect(portfolioCardSource).toContain( + "lg:w-[340px] lg:shrink-0", + ); + expect(portfolioCardSource).toContain( + "max-w-[280px] sm:max-w-[360px] lg:max-w-none aspect-[40/21]", + ); + expect(portfolioCardSource).toContain( + 'sizes="(min-width: 1024px) 300px, (min-width: 640px) 360px, (min-width: 358px) 280px, calc(100vw - 80px)"', + ); + expect(portfolioCardSource).toContain( + 'className="min-w-0 flex flex-col p-6 lg:flex-1"', + ); + expect(portfolioCardSource).toContain("lg:mt-auto lg:pt-4"); + expect(portfolioCardSource).toContain("inline-flex self-start"); + expect(portfolioCardSource).not.toContain('expanded: boolean'); + expect(portfolioPageSource).not.toMatch( + /\n\s+expanded=\{detailsExpanded\}/, + ); + expect(portfolioCardSource).not.toMatch(/(?:min-)?h-\[(?:280|360)px\]/); + expect(portfolioCardSource).not.toContain("line-clamp"); + expect(portfolioCardSource).not.toContain("truncate"); + expect(portfolioCardSource).not.toContain("w-full h-full object-center"); + }); });