fix(dashboard): show the blood pressure axis in mmHg, not Hg

The dashboard's blood pressure chart passed `yAxisUnit="Hg"` beside
`unit="mmHg"`, a shortening carried since the first release, so every
tick read "154 Hg". The override is gone; "mmHg" is four characters and
fits the axis gutter like "bpm" and "mg/dL" do.

A unit with a space of its own ("/ 5") is now joined with no-break
spaces as well, so Recharts cannot wrap it either. A guard fails on any
`yAxisUnit` that is a cut-down form of the `unit` beside it.
This commit is contained in:
Marc-André Bombeck committed 2026-10-09 12:56:32 +02:00
1 parent 2638174b66
commit 4c06ecafe3
3 files changed
+60 -2

No files matched your search

-1
View File
@@ -1780,7 +1780,6 @@ export default function DashboardPageClient({
title={t("dashboard.bloodPressure")}
colors={["var(--chart-3)", "var(--chart-4)"]}
unit="mmHg"
yAxisUnit="Hg"
targetZones={bpTargetZones}
compareBaseline={compareBaseline}
userTimezone={user?.timezone}
@@ -39,6 +39,11 @@ describe("axis unit suffix", () => {
expect(axisUnitSuffix(null)).toBeUndefined();
});
it("keeps a unit with a space of its own on one line", () => {
expect(axisUnitSuffix("/ 5")).toBe("\u00a0/\u00a05");
expect(axisUnitSuffix("mmHg")).toBe("\u00a0mmHg");
});
it("finds the axis units it is meant to police", () => {
// A matcher that finds nothing would pass the check below by default.
expect(axisUnitProps().length).toBeGreaterThanOrEqual(6);
@@ -55,6 +60,59 @@ describe("axis unit suffix", () => {
});
});
/**
* Every tag in the app that names both a `unit` and a `yAxisUnit` literal.
* The dashboard's blood pressure chart carried `yAxisUnit="Hg"` beside
* `unit="mmHg"` from the first release on, so its axis read "154 Hg".
*/
function axisUnitOverrides(): Array<{
file: string;
unit: string;
axis: string;
}> {
const out: Array<{ file: string; unit: string; axis: string }> = [];
for (const root of ["app", "components"]) {
const dir = join(process.cwd(), "src", root);
for (const rel of walkSourceFiles(dir, {
floor: 100,
extensions: [".tsx"],
})) {
if (rel.includes("__tests__")) continue;
const src = stripComments(readFileSync(join(dir, rel), "utf8"));
// The tag around each override: back to the previous element's end,
// forward to the next one's. A prop holding JSX (`icon={<X />}`) can
// sit inside, so the tag is not cut at the first `<`.
for (const m of src.matchAll(/\byAxisUnit="([^"]*)"/g)) {
const before = src.slice(0, m.index);
const from = Math.max(0, before.lastIndexOf("/>"), m.index - 1500);
const afterEnd = src.indexOf("/>", m.index);
const tag = src.slice(from, afterEnd === -1 ? undefined : afterEnd);
const unit = /\bunit="([^"]*)"/.exec(tag);
if (unit)
out.push({ file: `${root}/${rel}`, unit: unit[1], axis: m[1] });
}
}
}
return out;
}
describe("axis unit overrides", () => {
it("finds the overrides it is meant to police", () => {
expect(axisUnitOverrides().length).toBeGreaterThanOrEqual(5);
});
it("never cuts a unit short on the axis", () => {
const cut = axisUnitOverrides()
.filter(
({ unit, axis }) => axis !== "" && axis !== unit && unit.includes(axis),
)
.map(
({ file, unit, axis }) => `${file}: unit="${unit}" yAxisUnit="${axis}"`,
);
expect(cut).toEqual([]);
});
});
describe("axisTickUnitSuffix", () => {
it("keeps a short unit on the ticks", () => {
expect(axisTickUnitSuffix("bpm")).toBe(axisUnitSuffix("bpm"));
+2 -1
View File
@@ -11,7 +11,8 @@
export function axisUnitSuffix(
unit: string | null | undefined,
): string | undefined {
return unit ? ` ${unit}` : undefined;
// A space inside the unit ("/ 5") would break the label the same way.
return unit ? ` ${unit.replace(/ /g, "\u00a0")}` : undefined;
}
/**