revert(charts): mood chart shows simple dots instead of emoji at data points

Marc explicitly rejected smileys in the mood chart. Drop the emoji
glyph map and the SVG <text> dot factory; the line now renders plain
Recharts dots and the y-axis already labels each integer (very low /
low / okay / good / great), so the chart stays scannable without a
glyph.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Marc-André BombeckandClaude Opus 4.7 committed 2026-05-10 10:19:46 +02:00
1 parent 008a8fba3e
commit 06f18dfbdb
2 files changed
+25 -46

No files matched your search

@@ -1,5 +1,7 @@
import { describe, it, expect, vi } from "vitest";
import { renderToStaticMarkup } from "react-dom/server";
import { readFileSync } from "node:fs";
import { fileURLToPath } from "node:url";
/**
* v1.4.18 — MoodChart clean-line revert (gradient + emoji rolled back).
@@ -56,4 +58,20 @@ describe("<MoodChart> v1.4.18 clean-line revert", () => {
expect(html).not.toContain("chart-gradient-mood");
expect(html).not.toContain("linearGradient");
});
it("does NOT render emoji glyphs at data points (source check)", async () => {
// Marc explicitly rejected smileys, especially in the mood chart.
// Recharts does not paint <Line> dots during SSR (the dot callback
// only fires after first client render), so the emoji wouldn't
// surface in renderToStaticMarkup output anyway. Inspecting the
// module source guarantees the glyph map and the `<text>` glyph
// factory are gone — we don't want a regression where someone
// reintroduces them and SSR tests still pass.
const moduleUrl = new URL("../mood-chart.tsx", import.meta.url);
const src = readFileSync(fileURLToPath(moduleUrl), "utf8");
expect(src).not.toContain("moodEmoji");
expect(src).not.toContain("mood-emoji-glyph");
expect(src).not.toMatch(/[\u{1F600}-\u{1F64F}]/u);
});
});
+7 -46
View File
@@ -56,7 +56,7 @@ interface MoodChartProps {
/**
* v1.4.16 phase B5c — compact mode for embedding inside the
* RecommendationCard. Hides the range tabs / toggle row and shrinks
* padding. Tooltip + emoji glyphs at data points stay intact.
* padding. Tooltip stays intact.
*/
mini?: boolean;
/**
@@ -457,16 +457,10 @@ export function MoodChart({
5: t("charts.moodLabel5"),
};
// v1.4.16 B1a — emoji glyph per integer mood score. Apple Health
// surfaces a smiley/frown alongside the value; mirroring that here
// makes the chart scannable without a legend.
const moodEmoji: Record<number, string> = {
1: "\u{1F616}", // 😖
2: "\u{1F641}", // 🙁
3: "\u{1F610}", // 😐
4: "\u{1F642}", // 🙂
5: "\u{1F604}", // 😄
};
// v1.4.18 — emoji glyph map removed. Marc explicitly rejected
// smileys in the mood chart; the line now uses plain Recharts dots
// and the y-axis already labels each integer (very low / low / okay
// / good / great) so the chart is fully scannable without a glyph.
const formatMoodTick = (value: number): string => {
return moodLabels[value] ?? String(value);
@@ -812,41 +806,8 @@ export function MoodChart({
name="score"
stroke={COLOR_MAIN}
strokeWidth={2}
// v1.4.16 B1a — emoji glyph at every data point. The
// dot prop accepts a function returning an SVG node,
// so we render <text> with the emoji centred over the
// (cx, cy) the line layout already computed.
dot={(props) => {
const { cx, cy, payload, key } = props as {
cx?: number;
cy?: number;
payload?: ChartDataPoint;
key?: string | number;
};
if (
typeof cx !== "number" ||
typeof cy !== "number" ||
!payload
) {
return <g key={key} />;
}
const rounded = Math.round(payload.score);
const glyph = moodEmoji[rounded] ?? "•";
return (
<text
key={key}
x={cx}
y={cy + 5}
textAnchor="middle"
fontSize={14}
data-slot="mood-emoji-glyph"
data-score={rounded}
>
{glyph}
</text>
);
}}
activeDot={{ r: 6 }}
dot={{ r: 3, fill: COLOR_MAIN }}
activeDot={{ r: 5 }}
connectNulls
isAnimationActive={animationsEnabled}
animationDuration={animationsEnabled ? 600 : 0}