Add a subtitle slot to the insights overview section heading

Detail pages already render a one-line description under their heading;
the overview section headings had no slot for one. Add an optional
subtitle to SectionHeading, rendered in the same muted typography, and
wire it into the obvious top-level sections: Trends (folding its existing
right-aligned caption into the slot), Your health scores, and Your
vitals.
This commit is contained in:
Marc-André Bombeck committed 2026-06-27 13:02:41 +02:00
1 parent f5e9d875cc
commit 07b65ade88
6 files changed
+31 -8

No files matched your search

@@ -729,6 +729,7 @@ export function VitalsDashboard({ batch, layout, className }: DashboardProps) {
<SectionHeading
icon={HeartPulse}
title={t("insights.derived.vitals.sectionTitle")}
subtitle={t("insights.derived.vitals.sectionSubtitle")}
/>
<div
data-slot="vitals-dashboard-error"
@@ -774,6 +775,7 @@ export function VitalsDashboard({ batch, layout, className }: DashboardProps) {
<SectionHeading
icon={HeartPulse}
title={t("insights.derived.vitals.sectionTitle")}
subtitle={t("insights.derived.vitals.sectionSubtitle")}
/>
<div
data-slot="vitals-dashboard-grid"
@@ -211,6 +211,7 @@ export function WellnessScores({
<SectionHeading
icon={Activity}
title={t("insights.derived.scores.sectionTitle")}
subtitle={t("insights.derived.scores.sectionSubtitle")}
/>
<div
data-slot="wellness-scores-error"
@@ -394,6 +395,7 @@ export function WellnessScores({
<SectionHeading
icon={Activity}
title={t("insights.derived.scores.sectionTitle")}
subtitle={t("insights.derived.scores.sectionSubtitle")}
/>
<div
data-slot="wellness-scores-grid"
+22 -3
View File
@@ -34,6 +34,14 @@ interface SectionHeadingProps {
icon: ComponentType<{ className?: string }>;
/** Heading text rendered inside the `<h2>`. */
title: ReactNode;
/**
* Optional one-line description rendered directly under the `<h2>`, in the
* same muted typography the detail pages use beneath their headings
* (`text-muted-foreground text-sm`). Opt-in per section so the overview can
* carry the "descriptive line under every heading" rule without forcing a
* subtitle where none reads well.
*/
subtitle?: ReactNode;
/** Optional trailing affordance pinned to the right edge of the row. */
action?: ReactNode;
/** Optional id on the `<h2>`, e.g. for an `aria-labelledby` link. */
@@ -44,6 +52,7 @@ interface SectionHeadingProps {
export function SectionHeading({
icon: Icon,
title,
subtitle,
action,
id,
className,
@@ -58,9 +67,19 @@ export function SectionHeading({
>
<div className="flex min-w-0 items-center gap-2">
<Icon className="text-foreground h-5 w-5 shrink-0" aria-hidden="true" />
<h2 id={id} className="text-base font-semibold">
{title}
</h2>
<div className="min-w-0">
<h2 id={id} className="text-base font-semibold">
{title}
</h2>
{subtitle ? (
<p
data-slot="section-heading-subtitle"
className="text-muted-foreground text-sm"
>
{subtitle}
</p>
) : null}
</div>
</div>
{action ? (
<div className="flex shrink-0 items-center gap-2">{action}</div>
+1 -5
View File
@@ -200,11 +200,7 @@ export function TrendsRow({
<SectionHeading
icon={TrendingUp}
title={t("insights.trendsRow.title")}
action={
<p className="text-muted-foreground text-xs">
{t("insights.trendsRow.subtitle")}
</p>
}
subtitle={t("insights.trendsRow.subtitle")}
/>
{/* v1.4.22 A4 — equal-height cards. The annotation prose
below each chart varies in length, which used to leave the