From 38629d41ed134ebc93b5f508b0e59531f14245f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Mon, 29 Jun 2026 14:53:53 +0200 Subject: [PATCH] fix(insights): repair the score-anatomy layout and align Coach affordances The readiness/recovery score-anatomy detail card rendered broken: the contributor factors were obscured and the method text overlapped the title and ring on every breakpoint. The provenance explainer no longer ships a collapsible info glyph; it renders its full method body inline, but the anatomy view still wrapped it in an absolute top-right box, which pulled the whole paragraph out of flow and painted it over the centred title, ring and contributor rows. Render the method caption in normal flow at the foot of the card so the factors read again and nothing overlaps. Move the weekly/monthly review Coach hand-off to the icon-only affordance pinned top-right, matching the assessment cards instead of a trailing text button. Widen the Coach conversation-history page to the standard content width so the conversation list no longer sits in an artificially narrow column. --- src/app/coach/conversations/page.tsx | 2 +- .../__tests__/score-anatomy-view.test.tsx | 6 ++ .../insights/derived/score-anatomy-view.tsx | 30 ++++---- .../insights/period-narrative-card.tsx | 77 ++++++++++--------- 4 files changed, 60 insertions(+), 55 deletions(-) diff --git a/src/app/coach/conversations/page.tsx b/src/app/coach/conversations/page.tsx index 3d68a8fbf..dfa955015 100644 --- a/src/app/coach/conversations/page.tsx +++ b/src/app/coach/conversations/page.tsx @@ -120,7 +120,7 @@ function CoachConversationsBody() { } return ( -
+

", () => { expect(html).toContain('data-contributor="respiratory"'); expect(html).toContain('data-present="false"'); expect(html).toContain('data-slot="provenance-explainer-method"'); + expect(html).toContain("A blend of deviation components."); // v1.15.12 F4 — the "keine klinische Bewertung" footer line is removed; // the non-clinical framing now lives in the inline provenance method. expect(html).not.toContain('data-slot="score-anatomy-disclaimer"'); + // Regression guard: `ProvenanceExplainer` renders its full method body + // inline (the v1.22 refactor dropped the ⓘ glyph), so it must sit in + // normal flow — never pulled out via `absolute top-3 right-3`, which + // painted the whole paragraph over the title, ring and contributor rows. + expect(html).not.toContain("absolute top-3 right-3"); }); it("tints the card + leans the ring hue when a hue is passed (F1)", () => { diff --git a/src/components/insights/derived/score-anatomy-view.tsx b/src/components/insights/derived/score-anatomy-view.tsx index 8bac63efb..bbc2b1dc5 100644 --- a/src/components/insights/derived/score-anatomy-view.tsx +++ b/src/components/insights/derived/score-anatomy-view.tsx @@ -126,24 +126,12 @@ export function ScoreAnatomyView({ : undefined } className={cn( - "relative flex flex-col gap-5 rounded-xl border p-5", + "flex flex-col gap-5 rounded-xl border p-5", hue ? "wellness-detail-card" : "border-border bg-card", className, )} aria-label={typeof title === "string" ? title : undefined} > - {/* v1.15.12 F5 — the ⓘ explainer is pinned TOP-right at heading height - (it used to trail the card at bottom-right). Absolute so it never - shifts the centred hero title; the trigger keeps its 44px touch - target + popover/sheet behaviour. */} -
- -
- {/* Hero: title + ring + caption */}

)} - {/* v1.15.12 F4 — the "Richtwert — keine klinische Bewertung" footer line - is gone; the method + cited standard live behind the provenance - explainer (now top-right, F5), which carries the non-clinical framing - where it belongs. The composition (contributor rows above) stays. */} + {/* The plain-language method caption closes the card, in normal flow. + `ProvenanceExplainer` (v1.22) is no longer a top-right ⓘ glyph — it + renders its full method body inline as a muted caption, so it must + sit in the document flow at the foot of the surface. The earlier + `absolute top-right` wrapper yanked the whole paragraph out of flow + and painted it over the centred title, ring and contributor rows on + every breakpoint; rendering it here keeps the spine readable. */} + ); } diff --git a/src/components/insights/period-narrative-card.tsx b/src/components/insights/period-narrative-card.tsx index 222401b94..ed5681a2f 100644 --- a/src/components/insights/period-narrative-card.tsx +++ b/src/components/insights/period-narrative-card.tsx @@ -11,7 +11,7 @@ import { useAuth } from "@/hooks/use-auth"; import { cn } from "@/lib/utils"; import { Skeleton } from "@/components/ui/skeleton"; import { SectionHeading } from "@/components/insights/section-heading"; -import { AskCoachAction } from "@/components/insights/ask-coach-action"; +import { AskCoachIconButton } from "@/components/insights/ask-coach-action"; import { ProseBlocks } from "@/components/insights/prose-blocks"; import { apiGet } from "@/lib/api/api-fetch"; @@ -142,29 +142,45 @@ export function PeriodNarrativeCard({ data-period={period} className={SHELL} > - {/* Week / month toggle. Calm segmented control, no chart. */} -
- {(["week", "month"] as const).map((p) => { - const active = period === p; - return ( - - ); - })} + {/* Header row: week / month toggle on the left, the icon-only Coach + hand-off pinned top-right. Matches the assessment cards, which carry + the same single `` in their header's right slot + (no text label, tooltip + accessible name). The summary spans the + whole picture for the window, so no scope: the default snapshot + reads best. */} +
+ {/* Calm segmented control, no chart. */} +
+ {(["week", "month"] as const).map((p) => { + const active = period === p; + return ( + + ); + })} +
+
{/* v1.22 (W6) — real paragraphs via the shared ProseBlocks helper @@ -184,19 +200,6 @@ export function PeriodNarrativeCard({ user?.timezone, )}

- - {/* v1.21.0 (C4 H2) — hand the period summary to the Coach. It spans - the whole picture for the window, so no scope: the default - snapshot reads best. */} -
- -
);