diff --git a/src/app/page-client.tsx b/src/app/page-client.tsx index 8afce7e8c..63c6ccf7f 100644 --- a/src/app/page-client.tsx +++ b/src/app/page-client.tsx @@ -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} diff --git a/src/lib/charts/__tests__/axis-unit.test.ts b/src/lib/charts/__tests__/axis-unit.test.ts index 121a0cce3..80c095c0c 100644 --- a/src/lib/charts/__tests__/axis-unit.test.ts +++ b/src/lib/charts/__tests__/axis-unit.test.ts @@ -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={}`) 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")); diff --git a/src/lib/charts/axis-unit.ts b/src/lib/charts/axis-unit.ts index abdd2ac50..62656b49b 100644 --- a/src/lib/charts/axis-unit.ts +++ b/src/lib/charts/axis-unit.ts @@ -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; } /**