diff --git a/src/components/insights/__tests__/sub-page-shell.test.tsx b/src/components/insights/__tests__/sub-page-shell.test.tsx
index 4873a42e7..e586b2329 100644
--- a/src/components/insights/__tests__/sub-page-shell.test.tsx
+++ b/src/components/insights/__tests__/sub-page-shell.test.tsx
@@ -47,7 +47,30 @@ describe("", () => {
,
);
// The shell uses a `
` for the description; no `
` appears when
- // the description prop is absent.
+ // neither a description nor an explainer metric is supplied.
expect(html).not.toMatch(/
]*class="text-muted-foreground/);
});
+
+ it("renders the explainer body inline beneath the heading", () => {
+ const html = render(
+
+
+ ,
+ );
+ // 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(
+
+
+ ,
+ );
+ // The `?` glyph stays available alongside the inline caption.
+ expect(html).toMatch(/data-slot="metric-explainer-trigger"/);
+ });
});
diff --git a/src/components/insights/sub-page-shell.tsx b/src/components/insights/sub-page-shell.tsx
index cc2c84566..b26575fe0 100644
--- a/src/components/insights/sub-page-shell.tsx
+++ b/src/components/insights/sub-page-shell.tsx
@@ -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.{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.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({
) : null}
+ {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.
+
+ {t(`insights.subPage.explainer.${explainerMetric}Body`)}
+
+ ) : null}
{description ? (
{description}
) : null}