From 6de53174164e2680a24e9d8bddf9940149836db6 Mon Sep 17 00:00:00 2001 From: jlightner Date: Tue, 31 Mar 2026 06:15:25 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20Replaced=20plain=20list=20rendering=20o?= =?UTF-8?q?f=20related=20techniques=20with=20a=20respon=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - "frontend/src/api/public-client.ts" - "frontend/src/pages/TechniquePage.tsx" - "frontend/src/App.css" GSD-Task: S02/T02 --- .gsd/milestones/M010/slices/S02/S02-PLAN.md | 2 +- .../M010/slices/S02/tasks/T01-VERIFY.json | 16 ++++ .../M010/slices/S02/tasks/T02-SUMMARY.md | 81 +++++++++++++++++++ frontend/src/App.css | 55 ++++++++++--- frontend/src/api/public-client.ts | 3 + frontend/src/pages/TechniquePage.tsx | 22 +++-- 6 files changed, 160 insertions(+), 19 deletions(-) create mode 100644 .gsd/milestones/M010/slices/S02/tasks/T01-VERIFY.json create mode 100644 .gsd/milestones/M010/slices/S02/tasks/T02-SUMMARY.md diff --git a/.gsd/milestones/M010/slices/S02/S02-PLAN.md b/.gsd/milestones/M010/slices/S02/S02-PLAN.md index ac9933d..d0fadef 100644 --- a/.gsd/milestones/M010/slices/S02/S02-PLAN.md +++ b/.gsd/milestones/M010/slices/S02/S02-PLAN.md @@ -61,7 +61,7 @@ - Estimate: 45m - Files: backend/schemas.py, backend/routers/techniques.py, backend/tests/test_public_api.py - Verify: cd backend && python -m pytest tests/test_public_api.py -x -v 2>&1 | tail -20 -- [ ] **T02: Frontend card-based related techniques section** — Replace the plain list rendering of related techniques with a responsive card grid. Update the TypeScript interface to match the enriched backend schema. +- [x] **T02: Replaced plain list rendering of related techniques with a responsive card grid showing title, creator name, category badge, and reason text** — Replace the plain list rendering of related techniques with a responsive card grid. Update the TypeScript interface to match the enriched backend schema. ## Steps diff --git a/.gsd/milestones/M010/slices/S02/tasks/T01-VERIFY.json b/.gsd/milestones/M010/slices/S02/tasks/T01-VERIFY.json new file mode 100644 index 0000000..8a297ad --- /dev/null +++ b/.gsd/milestones/M010/slices/S02/tasks/T01-VERIFY.json @@ -0,0 +1,16 @@ +{ + "schemaVersion": 1, + "taskId": "T01", + "unitId": "M010/S02/T01", + "timestamp": 1774937639249, + "passed": true, + "discoverySource": "task-plan", + "checks": [ + { + "command": "cd backend", + "exitCode": 0, + "durationMs": 7, + "verdict": "pass" + } + ] +} diff --git a/.gsd/milestones/M010/slices/S02/tasks/T02-SUMMARY.md b/.gsd/milestones/M010/slices/S02/tasks/T02-SUMMARY.md new file mode 100644 index 0000000..b3895ae --- /dev/null +++ b/.gsd/milestones/M010/slices/S02/tasks/T02-SUMMARY.md @@ -0,0 +1,81 @@ +--- +id: T02 +parent: S02 +milestone: M010 +provides: [] +requires: [] +affects: [] +key_files: ["frontend/src/api/public-client.ts", "frontend/src/pages/TechniquePage.tsx", "frontend/src/App.css"] +key_decisions: ["CSS grid with 1fr/1fr columns at 600px breakpoint for responsive card layout", "Badge uses inline-block with align-self:flex-start to avoid stretching"] +patterns_established: [] +drill_down_paths: [] +observability_surfaces: [] +duration: "" +verification_result: "Frontend build passes with zero errors (48 modules, 743ms). grep confirms 6 related-card CSS rules and creator_name in the TypeScript interface. Backend tests require ub01 PostgreSQL — not runnable locally." +completed_at: 2026-03-31T06:15:19.216Z +blocker_discovered: false +--- + +# T02: Replaced plain list rendering of related techniques with a responsive card grid showing title, creator name, category badge, and reason text + +> Replaced plain list rendering of related techniques with a responsive card grid showing title, creator name, category badge, and reason text + +## What Happened +--- +id: T02 +parent: S02 +milestone: M010 +key_files: + - frontend/src/api/public-client.ts + - frontend/src/pages/TechniquePage.tsx + - frontend/src/App.css +key_decisions: + - CSS grid with 1fr/1fr columns at 600px breakpoint for responsive card layout + - Badge uses inline-block with align-self:flex-start to avoid stretching +duration: "" +verification_result: passed +completed_at: 2026-03-31T06:15:19.238Z +blocker_discovered: false +--- + +# T02: Replaced plain list rendering of related techniques with a responsive card grid showing title, creator name, category badge, and reason text + +**Replaced plain list rendering of related techniques with a responsive card grid showing title, creator name, category badge, and reason text** + +## What Happened + +Updated the RelatedLinkItem TypeScript interface with creator_name, topic_category, and reason fields from T01's backend enrichment. Replaced the ul list in TechniquePage.tsx with a CSS grid of cards — each card shows the technique title as a link, creator name, topic category as a pill badge, and scoring reason. All fields conditionally rendered for graceful degradation. Added responsive grid CSS using existing design tokens: single column on mobile, two columns at 600px+. + +## Verification + +Frontend build passes with zero errors (48 modules, 743ms). grep confirms 6 related-card CSS rules and creator_name in the TypeScript interface. Backend tests require ub01 PostgreSQL — not runnable locally. + +## Verification Evidence + +| # | Command | Exit Code | Verdict | Duration | +|---|---------|-----------|---------|----------| +| 1 | `cd frontend && npm run build 2>&1 | tail -10` | 0 | ✅ pass | 2800ms | +| 2 | `grep -c 'related-card' frontend/src/App.css` | 0 | ✅ pass | 50ms | +| 3 | `grep -q 'creator_name' frontend/src/api/public-client.ts` | 0 | ✅ pass | 50ms | + + +## Deviations + +None. + +## Known Issues + +Backend test suite cannot run locally — requires PostgreSQL on ub01:5433. + +## Files Created/Modified + +- `frontend/src/api/public-client.ts` +- `frontend/src/pages/TechniquePage.tsx` +- `frontend/src/App.css` + + +## Deviations +None. + +## Known Issues +Backend test suite cannot run locally — requires PostgreSQL on ub01:5433. diff --git a/frontend/src/App.css b/frontend/src/App.css index f21728f..69d9525 100644 --- a/frontend/src/App.css +++ b/frontend/src/App.css @@ -1781,27 +1781,62 @@ a.app-footer__repo:hover { margin-bottom: 0.5rem; } -.technique-related__list { - list-style: none; - display: flex; - flex-direction: column; - gap: 0.375rem; +.technique-related__grid { + display: grid; + grid-template-columns: 1fr; + gap: 0.75rem; } -.technique-related__list a { +@media (min-width: 600px) { + .technique-related__grid { + grid-template-columns: 1fr 1fr; + } +} + +.related-card { + background: var(--color-surface-card); + border: 1px solid var(--color-border); + border-radius: 0.5rem; + padding: 0.875rem 1rem; + display: flex; + flex-direction: column; + gap: 0.25rem; +} + +.related-card__title { color: var(--color-link-accent); text-decoration: none; + font-weight: 600; font-size: 0.9375rem; } -.technique-related__list a:hover { +.related-card__title:hover { text-decoration: underline; } -.technique-related__rel { - font-size: 0.75rem; +.related-card__creator { + font-size: 0.8125rem; color: var(--color-text-muted); - margin-left: 0.375rem; +} + +.related-card__badge { + display: inline-block; + align-self: flex-start; + font-size: 0.6875rem; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.03em; + padding: 0.125rem 0.5rem; + border-radius: 999px; + background: var(--color-badge-bg, rgba(255, 255, 255, 0.08)); + color: var(--color-badge-text, var(--color-text-muted)); +} + +.related-card__reason { + font-size: 0.75rem; + font-style: italic; + color: var(--color-text-muted); + margin: 0; } /* ══════════════════════════════════════════════════════════════════════════════ diff --git a/frontend/src/api/public-client.ts b/frontend/src/api/public-client.ts index 0094fcd..18d2980 100644 --- a/frontend/src/api/public-client.ts +++ b/frontend/src/api/public-client.ts @@ -49,6 +49,9 @@ export interface RelatedLinkItem { target_title: string; target_slug: string; relationship: string; + creator_name: string; + topic_category: string; + reason: string; } export interface TechniquePageDetail { diff --git a/frontend/src/pages/TechniquePage.tsx b/frontend/src/pages/TechniquePage.tsx index 842fe40..c670987 100644 --- a/frontend/src/pages/TechniquePage.tsx +++ b/frontend/src/pages/TechniquePage.tsx @@ -495,18 +495,24 @@ export default function TechniquePage() { {technique.related_links.length > 0 && (

Related Techniques

- +
)}