mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-07 04:12:04 +00:00
feat(insights): show the metric explainer inline under each category heading
The per-category explainer text only lived behind the "?" popover next to the heading. Render the same localised definition inline as a muted caption directly beneath the title, where the short scaffold line already sits, so the one- to two-sentence definition is discoverable without a tap. Both surfaces read the identical insights.subPage.explainer.<metric>Body key, so there is no duplicated copy and all six locales stay covered. The "?" glyph stays in place as the always-available pointer to the same text. HealthkitMetricPage already forwards explainerMetric to the shell, so every routed metric sub-page picks up the inline caption from this one change.
This commit is contained in:
1 parent
0e3a8f9cd3
commit
c2808a9c70
2 files changed
+45
-1
No files matched your search
@@ -47,7 +47,30 @@ describe("<SubPageShell>", () => {
|
||||
</SubPageShell>,
|
||||
);
|
||||
// The shell uses a `<p>` for the description; no `<p>` appears when
|
||||
// the description prop is absent.
|
||||
// neither a description nor an explainer metric is supplied.
|
||||
expect(html).not.toMatch(/<p[^>]*class="text-muted-foreground/);
|
||||
});
|
||||
|
||||
it("renders the explainer body inline beneath the heading", () => {
|
||||
const html = render(
|
||||
<SubPageShell title="Blood pressure" explainerMetric="bloodPressure">
|
||||
<span />
|
||||
</SubPageShell>,
|
||||
);
|
||||
// The inline caption reuses the same body string the `?` popover reads.
|
||||
expect(html).toMatch(/data-slot="metric-explainer-inline"/);
|
||||
expect(html).toContain(
|
||||
"Blood pressure is the force your blood exerts on the artery walls",
|
||||
);
|
||||
});
|
||||
|
||||
it("keeps the explainer trigger glyph when explainerMetric is set", () => {
|
||||
const html = render(
|
||||
<SubPageShell title="Blood pressure" explainerMetric="bloodPressure">
|
||||
<span />
|
||||
</SubPageShell>,
|
||||
);
|
||||
// The `?` glyph stays available alongside the inline caption.
|
||||
expect(html).toMatch(/data-slot="metric-explainer-trigger"/);
|
||||
});
|
||||
});
|
||||
@@ -5,6 +5,7 @@ import { useEffect, useRef, type ReactNode } from "react";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { MetricExplainer } from "@/components/insights/metric-explainer";
|
||||
import { useScrollResetOnRoute } from "@/hooks/use-scroll-reset-on-route";
|
||||
import { useTranslations } from "@/lib/i18n/context";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
/**
|
||||
@@ -41,6 +42,13 @@ export interface SubPageShellProps {
|
||||
* The value is the metric key feeding
|
||||
* `insights.subPage.explainer.<metric>{Title,Body}`. Omitted on the
|
||||
* mother page; every routed metric sub-page passes its key.
|
||||
*
|
||||
* v1.8.4 — the same explainer body also renders inline as a muted
|
||||
* caption directly beneath the heading, so the one- to two-sentence
|
||||
* definition is visible without opening the popover. The `?` glyph
|
||||
* stays as the always-available pointer for the same copy. Both the
|
||||
* inline caption and the popover read the identical
|
||||
* `insights.subPage.explainer.<metric>Body` string — no duplicated copy.
|
||||
*/
|
||||
explainerMetric?: string;
|
||||
/**
|
||||
@@ -69,6 +77,7 @@ export function SubPageShell({
|
||||
focusOnMount = false,
|
||||
children,
|
||||
}: SubPageShellProps) {
|
||||
const { t } = useTranslations();
|
||||
// a11y: focus the heading on mount so a tab-strip navigation actually
|
||||
// moves screen-reader focus into the sub-page body. v1.4.27 MB7 /
|
||||
// CF-35 made the focus call opt-in via `focusOnMount` — the
|
||||
@@ -118,6 +127,18 @@ export function SubPageShell({
|
||||
</Badge>
|
||||
) : null}
|
||||
</div>
|
||||
{explainerMetric ? (
|
||||
// v1.8.4 — surface the explainer definition inline, reusing the
|
||||
// exact body string the `?` popover reads. Muted caption styling
|
||||
// matches the description paragraph below so the under-heading
|
||||
// band reads as one calm block.
|
||||
<p
|
||||
data-slot="metric-explainer-inline"
|
||||
className="text-muted-foreground text-sm leading-relaxed"
|
||||
>
|
||||
{t(`insights.subPage.explainer.${explainerMetric}Body`)}
|
||||
</p>
|
||||
) : null}
|
||||
{description ? (
|
||||
<p className="text-muted-foreground text-sm">{description}</p>
|
||||
) : null}
|
||||
|
||||
Reference in new issue
Block a user