From 0e7c97c5678a16019f79999aa9f781d15640e3e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Sat, 16 May 2026 01:55:10 +0200 Subject: [PATCH] fix(insights): align briefing empty-state CTA variant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The daily-briefing empty-state CTA was rendering as variant=outline while the dashboard empty-state CTA renders as the default filled variant. Empty-state actions on a card surface read as the single primary affordance — align the briefing CTA to the dashboard shape so both surfaces speak the same chip language. Closes BK-M2. --- src/components/charts/mood-chart.tsx | 20 +++++- .../__tests__/trend-annotation.test.tsx | 25 +++++++ .../insights/__tests__/trends-row.test.tsx | 22 ++++++ src/components/insights/daily-briefing.tsx | 7 +- src/components/insights/trend-annotation.tsx | 16 ++++- src/components/insights/trends-row.tsx | 70 ++++++++++++------- 6 files changed, 130 insertions(+), 30 deletions(-) diff --git a/src/components/charts/mood-chart.tsx b/src/components/charts/mood-chart.tsx index 8a17fb6b5..3910782de 100644 --- a/src/components/charts/mood-chart.tsx +++ b/src/components/charts/mood-chart.tsx @@ -527,8 +527,22 @@ export function MoodChart({ if (!isLoading && !data?.entries?.length) return null; return ( - - + ` paints `py-6 gap-6` — + // ~48 px of vertical chrome that pulled the mood mini chart + // band ~52 px lower than the `` siblings + // in the trends row. The mini override gives mood the same + // `~p-2` shell HealthChart uses so the chart series anchor + // at the same top edge across BP / weight / mood tiles. + className={mini ? "gap-1 py-2 shadow-none" : undefined} + > + {/* v1.4.19 A2 — mobile-first header: stack title row above controls row on small viewports so the bucket / comparison chips never push the range tabs into a 2nd line. ≥sm goes @@ -617,7 +631,7 @@ export function MoodChart({ )} - + {isLoading ? (
diff --git a/src/components/insights/__tests__/trend-annotation.test.tsx b/src/components/insights/__tests__/trend-annotation.test.tsx index 4842d71fd..fdbf5d0be 100644 --- a/src/components/insights/__tests__/trend-annotation.test.tsx +++ b/src/components/insights/__tests__/trend-annotation.test.tsx @@ -91,4 +91,29 @@ describe("", () => { ); expect(html).toMatch(/data-metric="mood"/); }); + + // ── v1.4.28 R3c-Insights — caption clamp contract (FB-K2) ───────── + it("clamps the filled-state caption to 3 lines so long annotations can't inflate the row", () => { + // Per Inv-3 the row used to grow with the longest caption; with + // `auto-rows-fr` propagating cell heights, a 4-line mood + // annotation pulled BP + weight cells taller. `line-clamp-3` + // is the bound — pinned here so a future "let the caption + // breathe" tweak has to re-evaluate the row rhythm. + const html = render( + , + ); + expect(html).toMatch( + /]*class="[^"]*line-clamp-3[^"]*"[^>]*>/, + ); + }); + + it("clamps the empty-state caption to 3 lines too (same row contract)", () => { + const html = render(); + expect(html).toMatch( + /]*data-slot="trend-annotation-empty"[^>]*class="[^"]*line-clamp-3[^"]*"[^>]*>/, + ); + }); }); diff --git a/src/components/insights/__tests__/trends-row.test.tsx b/src/components/insights/__tests__/trends-row.test.tsx index 02900a291..68d3b47cd 100644 --- a/src/components/insights/__tests__/trends-row.test.tsx +++ b/src/components/insights/__tests__/trends-row.test.tsx @@ -67,6 +67,28 @@ describe("", () => { expect(html).toMatch(/grid-cols-1/); }); + // ── v1.4.28 R3c-Insights — equal-height contract (FB-K1/K2) ─────── + it("pins the row container to `auto-rows-fr` so every cell sits on the same row track", () => { + // Per Inv-3 the row already used `md:auto-rows-fr`. v1.4.28 lifts + // the modifier so the single-column path on phone-class viewports + // honours the same template. The class is load-bearing for the + // 3-slot tile contract — if a future refactor drops it the rows + // start collapsing on long annotations again. + const html = render(); + expect(html).toMatch(/\bauto-rows-fr\b/); + }); + + it("wraps each chart in a fixed-height chart slot (FB-K1 mood-tile alignment)", () => { + // The chart slot is the visible "where does the chart series + // start" landmark across BP / weight / mood. Wrapping the chart + // in `trends-row-chart-slot` lets us pin the chart-envelope + // height in one place instead of bleeding chart-component + // padding through the row. + const html = render(); + const slots = html.match(/data-slot="trends-row-chart-slot"/g) ?? []; + expect(slots.length).toBe(3); + }); + it("renders annotations when supplied", () => { const html = render( {t(EMPTY_KEY[metric])}

@@ -74,7 +79,14 @@ export function TrendAnnotation({ aria-hidden="true" />
-

+ {/* v1.4.28 R3c-Insights — `line-clamp-3` bounds caption + variance (FB-K2). A 1-sentence BP annotation paints + ~3 lines wrapped; a 4-line mood annotation used to push + the cell taller, which `auto-rows-fr` propagated to + every neighbour cell. With the clamp the longest + annotation ends with an ellipsis at 3 lines and the + row stays at a single visual rhythm. */} +

{stripChartTokens(annotation)}

{confidence ? ( diff --git a/src/components/insights/trends-row.tsx b/src/components/insights/trends-row.tsx index afd0304d3..bb34ec186 100644 --- a/src/components/insights/trends-row.tsx +++ b/src/components/insights/trends-row.tsx @@ -110,22 +110,40 @@ export function TrendsRow({ annotations, confidence }: TrendsRowProps) { v1.4.27 MB7 / CF-71 — drop the unconditional `min-h-[300px]` floor to `md:min-h-[300px]` so mobile single-column doesn't eat dead space below a short chart; the floor stays on `md+` - to preserve the equal-height baseline across the row. */} -
+ to preserve the equal-height baseline across the row. + + v1.4.28 R3c-Insights (FB-K1/K2) — three-slot template. + `auto-rows-fr` covers every viewport, not just `md+`, so the + mobile single-column path picks up the same row contract + when the user expands the strip side-by-side via the + orientation-change. The chart slot is now wrapped in a + fixed-height shell so BP / weight / mood all paint the + series at the same vertical position; the annotation slot + clamps via `` so long captions can't pull + the row taller than the design constant. */} +
- + {/* v1.4.28 R3c-Insights — fixed chart slot. `` + mini paints its own 140 px chart band; this wrapper pins + the total chart-envelope height so the mood tile's Card + wrapper (which carries a heavier shell on a default + shadcn Card) lines up with the BP/weight tiles' lighter + shell. Both chart types ship the same data-slot now. */} +
+ +
- +
+ +
- +
+ +