mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 21:10:59 +00:00
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.
This commit is contained in:
1 parent
4266203d3a
commit
38629d41ed
4 files changed
+60
-55
No files matched your search
@@ -120,7 +120,7 @@ function CoachConversationsBody() {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="mx-auto flex h-full min-h-0 w-full max-w-2xl flex-col gap-4 px-4 pt-6 pb-4 md:px-6">
|
||||
<div className="mx-auto flex h-full min-h-0 w-full max-w-screen-xl flex-col gap-4 px-4 pt-6 pb-4 md:px-6">
|
||||
<header className="flex flex-col gap-3">
|
||||
<h1
|
||||
data-slot="coach-conversations-heading"
|
||||
|
||||
@@ -56,9 +56,15 @@ describe("<ScoreAnatomyView>", () => {
|
||||
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)", () => {
|
||||
|
||||
@@ -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. */}
|
||||
<div className="absolute top-3 right-3 z-10">
|
||||
<ProvenanceExplainer
|
||||
provenance={provenance}
|
||||
method={method}
|
||||
standard={standard}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Hero: title + ring + caption */}
|
||||
<div className="flex flex-col items-center gap-3 text-center">
|
||||
<h2
|
||||
@@ -199,10 +187,18 @@ export function ScoreAnatomyView({
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 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. */}
|
||||
<ProvenanceExplainer
|
||||
provenance={provenance}
|
||||
method={method}
|
||||
standard={standard}
|
||||
/>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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. */}
|
||||
<div className="flex gap-1 self-start">
|
||||
{(["week", "month"] as const).map((p) => {
|
||||
const active = period === p;
|
||||
return (
|
||||
<button
|
||||
key={p}
|
||||
type="button"
|
||||
aria-pressed={active}
|
||||
onClick={() => setPeriod(p)}
|
||||
className={cn(
|
||||
"focus-visible:ring-ring inline-flex min-h-11 items-center rounded-md px-2.5 py-1 text-xs font-medium transition-colors focus-visible:ring-2 focus-visible:outline-none",
|
||||
active
|
||||
? "bg-muted text-foreground"
|
||||
: "text-muted-foreground hover:text-foreground",
|
||||
)}
|
||||
>
|
||||
{p === "week"
|
||||
? t("insights.narrativeWeek")
|
||||
: t("insights.narrativeMonth")}
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
{/* 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 `<AskCoachIconButton>` 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. */}
|
||||
<div className="flex items-start justify-between gap-2">
|
||||
{/* Calm segmented control, no chart. */}
|
||||
<div className="flex gap-1">
|
||||
{(["week", "month"] as const).map((p) => {
|
||||
const active = period === p;
|
||||
return (
|
||||
<button
|
||||
key={p}
|
||||
type="button"
|
||||
aria-pressed={active}
|
||||
onClick={() => setPeriod(p)}
|
||||
className={cn(
|
||||
"focus-visible:ring-ring inline-flex min-h-11 items-center rounded-md px-2.5 py-1 text-xs font-medium transition-colors focus-visible:ring-2 focus-visible:outline-none",
|
||||
active
|
||||
? "bg-muted text-foreground"
|
||||
: "text-muted-foreground hover:text-foreground",
|
||||
)}
|
||||
>
|
||||
{p === "week"
|
||||
? t("insights.narrativeWeek")
|
||||
: t("insights.narrativeMonth")}
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<AskCoachIconButton
|
||||
question={t(
|
||||
period === "week"
|
||||
? "insights.coach.seed.periodWeek"
|
||||
: "insights.coach.seed.periodMonth",
|
||||
)}
|
||||
className="shrink-0"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* v1.22 (W6) — real paragraphs via the shared ProseBlocks helper
|
||||
@@ -184,19 +200,6 @@ export function PeriodNarrativeCard({
|
||||
user?.timezone,
|
||||
)}
|
||||
</p>
|
||||
|
||||
{/* 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. */}
|
||||
<div className="flex justify-end">
|
||||
<AskCoachAction
|
||||
question={t(
|
||||
period === "week"
|
||||
? "insights.coach.seed.periodWeek"
|
||||
: "insights.coach.seed.periodMonth",
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
|
||||
Reference in new issue
Block a user