fix(insights): paint mood bars at full saturation

The muted mood treatment (opacity-55 on the tag bars, fillOpacity 0.55 on the
distribution and weekday charts) read as a rendering glitch rather than a
deliberate calm tint. Drop the dimming so every mood bar paints at full
saturation in its level hue; the guard test now asserts the dimming stays gone.
A separate mood colour concept can be revisited later.
This commit is contained in:
Marc-André Bombeck committed 2026-06-21 10:16:06 +02:00
1 parent 7540d0b508
commit c9b1631da7
5 files changed
+21 -30

No files matched your search

@@ -6,11 +6,11 @@ import { MoodTagBreakdown } from "../mood-tag-breakdown";
import { MoodStructuredTagBreakdown } from "../mood-structured-tag-breakdown";
/**
* v1.16.8 — the tag-breakdown bars carry the same muted treatment as
* the mood Recharts charts (`fillOpacity={0.55}` on distribution /
* weekday / time-of-day). The CSS bars rendered the raw `--dracula-*`
* hues at full opacity, which made the two tag cards shout next to the
* matte charts above them. Pinned: every fill bar ships `opacity-55`.
* v1.19.0 — the muted mood treatment (`opacity-55` on the tag bars,
* `fillOpacity={0.55}` on the Recharts bars) read as a rendering glitch,
* so the bars now paint at full saturation in their level hue. This guard
* keeps the dimming from creeping back: every fill bar carries the level
* colour at full opacity.
*/
function render(node: React.ReactNode) {
@@ -19,8 +19,8 @@ function render(node: React.ReactNode) {
);
}
describe("mood tag bars — muted palette (v1.16.8)", () => {
it("free-text tag breakdown bars render at the shared chart opacity", () => {
describe("mood tag bars — full-saturation palette (v1.19.0)", () => {
it("free-text tag breakdown bars render at full opacity", () => {
const html = render(
<MoodTagBreakdown
tags={[
@@ -32,14 +32,14 @@ describe("mood tag bars — muted palette (v1.16.8)", () => {
const fills = html.match(/class="[^"]*absolute inset-y-0 left-0[^"]*"/g);
expect(fills).toHaveLength(2);
for (const fill of fills ?? []) {
expect(fill).toContain("opacity-55");
expect(fill).not.toContain("opacity-55");
}
// The level hue itself stays a Dracula token.
expect(html).toContain("var(--dracula-red)");
expect(html).toContain("var(--dracula-green)");
});
it("structured tag breakdown bars render at the shared chart opacity", () => {
it("structured tag breakdown bars render at full opacity", () => {
const html = render(
<MoodStructuredTagBreakdown
tags={[
@@ -56,6 +56,6 @@ describe("mood tag bars — muted palette (v1.16.8)", () => {
);
const fills = html.match(/class="[^"]*absolute inset-y-0 left-0[^"]*"/g);
expect(fills).toHaveLength(1);
expect(fills?.[0]).toContain("opacity-55");
expect(fills?.[0]).not.toContain("opacity-55");
});
});
@@ -111,13 +111,8 @@ export function MoodDistributionChart({
// than a missing slot. The coloured bar paints over the track
// for non-empty levels.
background={{ fill: "var(--secondary)", opacity: 0.35, radius: 3 }}
// v1.15.14 — the saturated full-bleed mood hues read as
// "erschlagend"; soften every bar to a muted tint of its level
// colour. The hue (= mood-level semantics) still distinguishes the
// bands, but the fill sits calmly over the card rather than
// shouting. Scoped to this chart only — the shared `--dracula-*`
// mood tokens (heatmap, legend) are untouched.
fillOpacity={0.55}
// v1.19.0 — bars paint at full saturation in their level colour;
// the earlier muted tint read as a rendering glitch.
>
{data.map((row) => (
<Cell
@@ -56,11 +56,10 @@ export function MoodStructuredTagBreakdown({
{row.label ?? t(row.labelKey)}
</span>
<div className="bg-secondary relative h-3 flex-1 overflow-hidden rounded-full">
{/* v1.16.8 — `opacity-55` matches the `fillOpacity={0.55}`
the mood Recharts bars carry (distribution / weekday /
time-of-day), so the tag bars read equally matte. */}
{/* v1.19.0 — full-saturation fill, matching the mood Recharts
bars (the earlier muted tint read as a rendering glitch). */}
<div
className="absolute inset-y-0 left-0 rounded-full opacity-55"
className="absolute inset-y-0 left-0 rounded-full"
style={{
width: `${(row.count / maxCount) * 100}%`,
backgroundColor: colorForScore(row.avgScore),
@@ -41,11 +41,10 @@ export function MoodTagBreakdown({ tags }: { tags: MoodTagRow[] }) {
{row.tag}
</span>
<div className="bg-secondary relative h-3 flex-1 overflow-hidden rounded-full">
{/* v1.16.8 — `opacity-55` matches the `fillOpacity={0.55}`
the mood Recharts bars carry (distribution / weekday /
time-of-day), so the tag bars read equally matte. */}
{/* v1.19.0 — full-saturation fill, matching the mood Recharts
bars (the earlier muted tint read as a rendering glitch). */}
<div
className="absolute inset-y-0 left-0 rounded-full opacity-55"
className="absolute inset-y-0 left-0 rounded-full"
style={{
width: `${(row.count / maxCount) * 100}%`,
backgroundColor: colorForScore(row.avgScore),
@@ -136,11 +136,9 @@ export function MoodWeekdayChart({ weekday }: { weekday: MoodWeekdayRow[] }) {
];
}}
/>
{/* v1.15.14 — soften the saturated mood hues to a muted tint
(the level semantics still distinguish the bars; the fill no
longer shouts). Scoped here — the shared `--dracula-*` mood
tokens used by the heatmap/legend stay untouched. */}
<Bar dataKey="value" radius={[3, 3, 0, 0]} fillOpacity={0.55}>
{/* v1.19.0 — bars paint at full saturation in their level colour;
the earlier muted tint read as a rendering glitch. */}
<Bar dataKey="value" radius={[3, 3, 0, 0]}>
{data.map((row) => (
<Cell
key={row.weekday}