diff --git a/src/components/charts/trend-card.tsx b/src/components/charts/trend-card.tsx index c7dfa5a00..127aeaf4f 100644 --- a/src/components/charts/trend-card.tsx +++ b/src/components/charts/trend-card.tsx @@ -272,10 +272,15 @@ export function TrendCard({ all-time + comparison-delta into a single line that stays scannable on Galaxy Fold (280 px) and Pixel 5 (375 px). The full layout returns at `>=sm`. */} + {/* v1.4.27 MB7 / CF-41 — the `hidden sm:block` gate retired + because the mobile-secondary block below is gone (CF-67 + vestigial wrapper drop). The callout paints on every + viewport; when the parent grid is tight on ` +
=sm`; on ` {t(avgAllTimeLabelKey)}:{" "} )}
- {/* v1.4.22 W5 reconcile (Design-H2) — combined secondary row - for `=sm` because the full layout above takes over. */} - {avgAllTime !== undefined && ( -
- - {t(avgAllTimeLabelKey)}:{" "} - - {avgAllTime !== null ? formatValue(avgAllTime) : "—"} - - - {compareBaseline !== "none" && compareDelta != null && ( - <> - - - {`Δ ${formatDelta(compareDelta)}${unit ? ` ${unit}` : ""} ${t( - compareBaseline === "lastMonth" - ? "comparison.captionLastMonth" - : "comparison.captionLastYear", - )}`} - - - )} -
- )} ); diff --git a/src/components/insights/insight-status-card.tsx b/src/components/insights/insight-status-card.tsx index d9dffd95e..7eeb943d2 100644 --- a/src/components/insights/insight-status-card.tsx +++ b/src/components/insights/insight-status-card.tsx @@ -1,9 +1,12 @@ "use client"; +import { useState } from "react"; + import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Loader2 } from "lucide-react"; import { useTranslations, useFormatters } from "@/lib/i18n/context"; import { stripChartTokens } from "@/lib/insights/chart-tokens"; +import { cn } from "@/lib/utils"; // ─── Types ──────────────────────────────────────────────── @@ -102,15 +105,68 @@ export function InsightStatusCard({ token surfaces verbatim. The producer side now strips too; this consumer-side wrap keeps existing caches clean while they roll forward. */} -

- {stripChartTokens(text)} -

+ ); } +/** + * v1.4.27 MB7 / CF-39 — collapsible status copy. The assessment text + * routinely lands at 3-5 paragraphs of dense narrative which dominates + * the surface on phones. The default collapses to 3 lines via + * `line-clamp-3`; a "Show more" toggle reveals the full body. Desktop + * users see the full text immediately because the clamp + toggle only + * mount when the source string is long enough to actually clip. + */ +function StatusBody({ text }: { text: string }) { + const { locale } = useTranslations(); + const [expanded, setExpanded] = useState(false); + // Cheap heuristic — only mount the toggle when the text is long + // enough that the 3-line clamp will hide content. ~220 characters + // covers the worst-case sm-viewport line at typical insights text + // density; below that we render plain so the user never sees a + // useless "Show more" affordance. + const isLong = text.length > 220; + if (!isLong) { + return ( +

{text}

+ ); + } + // v1.4.27 MB7 / CF-39 — toggle copy is two short strings; rather + // than reach into the catalogue (which this bucket cannot edit per + // the dispatch brief), the labels resolve against the locale prefix + // inline. The translation catalogue can claim these strings in a + // later cycle without breaking the contract. + const isDe = locale.startsWith("de"); + const showMoreLabel = isDe ? "Mehr anzeigen" : "Show more"; + const showLessLabel = isDe ? "Weniger anzeigen" : "Show less"; + return ( +
+

+ {text} +

+ +
+ ); +} + function LastUpdatedFooter({ updatedAt }: { updatedAt: string | null }) { const { t } = useTranslations(); const fmt = useFormatters(); diff --git a/src/components/insights/vo2-max-chart-row.tsx b/src/components/insights/vo2-max-chart-row.tsx index 27bce6f0f..c6e8938c0 100644 --- a/src/components/insights/vo2-max-chart-row.tsx +++ b/src/components/insights/vo2-max-chart-row.tsx @@ -135,10 +135,15 @@ export function Vo2MaxChartRow({

{unit}

- {/* Stat strip — latest / min / max / avg30 / Δ vs. prior period. */} + {/* Stat strip — latest / min / max / avg30 / Δ vs. prior period. + v1.4.27 MB7 / CF-38 — extend the 2-column phone grid all the + way to `