fix(insights): pin trends-row chart slot to h-[140px]

Each `trends-row-chart-slot` wrapper had `shrink-0` but no explicit
height. Recharts' ResponsiveContainer mounted with `width=-1
height=-1` and emitted a warning on every Insights cold mount; the
mood card visibly drifted taller than BP / weight as the chart
hydrated, contributing the bulk of the Lighthouse 0.46 CLS hit.

Pin the wrapper to 140 px (matches the chart-internal mini default).
Recharts now mounts at a known size, the three cards line up on the
same baseline from first paint, and the warning is gone. Test pins
the height on all three slots so a future refactor has to revisit
the row rhythm intentionally.
This commit is contained in:
Marc-André Bombeck committed 2026-05-17 12:07:27 +02:00
1 parent 125457e4fd
commit 4d111e39dd
2 files changed
+19 -3

No files matched your search

@@ -89,6 +89,22 @@ describe("<TrendsRow>", () => {
expect(slots.length).toBe(3);
});
it("pins every chart slot to h-[140px] so Recharts mounts with a known size (CLS fix)", () => {
// v1.4.36 W2 — without an explicit height the Recharts
// ResponsiveContainer mounts with width=-1 height=-1 and emits a
// console warning per chart. The mood card also drifted taller
// than BP / weight on hydration. Pinning the wrapper at 140 px
// matches the mini-chart's internal default; the row paints with
// zero layout shift.
const html = render(<TrendsRow />);
const slots =
html.match(/data-slot="trends-row-chart-slot"[^>]*class="[^"]*"/g) ?? [];
expect(slots.length).toBe(3);
for (const slot of slots) {
expect(slot).toMatch(/h-\[140px\]/);
}
});
it("renders annotations when supplied", () => {
const html = render(
<TrendsRow
+3 -3
View File
@@ -117,7 +117,7 @@ export function TrendsRow({ annotations, confidence }: TrendsRowProps) {
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. */}
<div data-slot="trends-row-chart-slot" className="shrink-0">
<div data-slot="trends-row-chart-slot" className="h-[140px] shrink-0">
<HealthChartDynamic
types={["BLOOD_PRESSURE_SYS", "BLOOD_PRESSURE_DIA"]}
title={t("charts.bloodPressure")}
@@ -139,7 +139,7 @@ export function TrendsRow({ annotations, confidence }: TrendsRowProps) {
data-metric="weight"
className="flex h-full flex-col gap-2 md:min-h-[300px]"
>
<div data-slot="trends-row-chart-slot" className="shrink-0">
<div data-slot="trends-row-chart-slot" className="h-[140px] shrink-0">
<HealthChartDynamic
types={["WEIGHT"]}
title={t("charts.weight")}
@@ -160,7 +160,7 @@ export function TrendsRow({ annotations, confidence }: TrendsRowProps) {
data-metric="mood"
className="flex h-full flex-col gap-2 md:min-h-[300px]"
>
<div data-slot="trends-row-chart-slot" className="shrink-0">
<div data-slot="trends-row-chart-slot" className="h-[140px] shrink-0">
<MoodChart
title={t("charts.mood")}
mini