diff --git a/packages/@ourworldindata/core-table/src/CoreTableColumns.ts b/packages/@ourworldindata/core-table/src/CoreTableColumns.ts index 09120f2fba..72bfe436e0 100644 --- a/packages/@ourworldindata/core-table/src/CoreTableColumns.ts +++ b/packages/@ourworldindata/core-table/src/CoreTableColumns.ts @@ -269,12 +269,6 @@ export abstract class AbstractCoreColumn { return undefined } - @imemo get displayUnit(): string | undefined { - return this.unit && this.unit !== this.shortUnit - ? this.unit.replace(/^\((.*)\)$/, "$1") - : undefined - } - // Returns a map where the key is a series slug such as "name" and the value is a set // of all the unique values that this column has for that particular series. getUniqueValuesGroupedBy( diff --git a/packages/@ourworldindata/grapher/src/axis/Axis.ts b/packages/@ourworldindata/grapher/src/axis/Axis.ts index a5ec9351ff..193e28782c 100644 --- a/packages/@ourworldindata/grapher/src/axis/Axis.ts +++ b/packages/@ourworldindata/grapher/src/axis/Axis.ts @@ -26,6 +26,7 @@ import { AxisConfig, AxisManager } from "./AxisConfig" import { MarkdownTextWrap } from "@ourworldindata/components" import { ColumnTypeMap, CoreColumn } from "@ourworldindata/core-table" import { GRAPHER_FONT_SCALE_12 } from "../core/GrapherConstants.js" +import { makeAxisLabel } from "../chart/ChartUtils" interface TickLabelPlacement { value: number @@ -503,21 +504,26 @@ abstract class AbstractAxis { this.axisManager?.detailsOrderedByReference, } - const displayUnit = this.formatColumn?.displayUnit - if (displayUnit) { + const axisLabel = makeAxisLabel({ + label: this.label, + unit: this.formatColumn?.unit, + shortUnit: this.formatColumn?.shortUnit, + }) + + if (axisLabel.unit) { return MarkdownTextWrap.fromFragments({ - main: { text: this.label, bold: true }, - secondary: { text: `(${displayUnit})` }, + main: { text: axisLabel.mainLabel, bold: true }, + secondary: { text: axisLabel.unit }, newLine: "avoid-wrap", textWrapProps, }) - } else { - return new MarkdownTextWrap({ - text: this.label, - fontWeight: 700, - ...textWrapProps, - }) } + + return new MarkdownTextWrap({ + text: axisLabel.mainLabel, + fontWeight: 700, + ...textWrapProps, + }) } @computed get labelHeight(): number { diff --git a/packages/@ourworldindata/grapher/src/chart/ChartUtils.tsx b/packages/@ourworldindata/grapher/src/chart/ChartUtils.tsx index 206b71cb57..0a0e7a0ad1 100644 --- a/packages/@ourworldindata/grapher/src/chart/ChartUtils.tsx +++ b/packages/@ourworldindata/grapher/src/chart/ChartUtils.tsx @@ -228,3 +228,35 @@ export function byHoverThenFocusState(series: { // background series rank lowest return 1 } + +export function makeAxisLabel({ + label, + unit, + shortUnit, +}: { + label: string + unit?: string + shortUnit?: string +}): { + mainLabel: string // shown in bold + unit?: string // shown in normal weight, usually in parens +} { + const displayUnit = unit && unit !== shortUnit ? unit : undefined + const unitInParens = displayUnit ? `(${displayUnit})` : undefined + + if (unitInParens) { + // extract text in parens at the end of the label, + // e.g. "Population (millions)" is split into "Population " and "(millions)" + const [_fullMatch, untrimmedMainLabelText, labelTextInParens] = + label.trim().match(/^(.*?)(\([^()]*\))?$/) ?? [] + const mainLabelText = untrimmedMainLabelText.trim() + + // don't show unit twice if it's contained in the label + const displayLabel = + labelTextInParens === unitInParens ? mainLabelText : label + + return { mainLabel: displayLabel, unit: unitInParens } + } + + return { mainLabel: label } +} diff --git a/packages/@ourworldindata/grapher/src/tooltip/Tooltip.scss b/packages/@ourworldindata/grapher/src/tooltip/Tooltip.scss index 13c0245cee..2d4d578107 100644 --- a/packages/@ourworldindata/grapher/src/tooltip/Tooltip.scss +++ b/packages/@ourworldindata/grapher/src/tooltip/Tooltip.scss @@ -117,14 +117,6 @@ .unit { font-weight: $medium; font-style: normal; - - &::before { - content: "("; - } - - &::after { - content: ")"; - } } } diff --git a/packages/@ourworldindata/grapher/src/tooltip/TooltipContents.tsx b/packages/@ourworldindata/grapher/src/tooltip/TooltipContents.tsx index a5e6d85c76..620207644a 100644 --- a/packages/@ourworldindata/grapher/src/tooltip/TooltipContents.tsx +++ b/packages/@ourworldindata/grapher/src/tooltip/TooltipContents.tsx @@ -19,6 +19,7 @@ import { TooltipValueRangeProps, TooltipContext, } from "./TooltipProps" +import { makeAxisLabel } from "../chart/ChartUtils.js" export const NO_DATA_COLOR = "#999" @@ -132,22 +133,25 @@ class Variable extends React.Component<{ if (column.isMissing || column.name === "time") return null - const { displayUnit, displayName } = column, - displayNotice = - uniq((notice ?? []).filter((t) => t !== undefined)) - .map((time) => - typeof time === "number" - ? column.formatTime(time) - : time - ) - .join("\u2013") || null + const { mainLabel: label, unit } = makeAxisLabel({ + label: column.displayName, + unit: column.unit, + shortUnit: column.shortUnit, + }) + + const displayNotice = + uniq((notice ?? []).filter((t) => t !== undefined)) + .map((time) => + typeof time === "number" ? column.formatTime(time) : time + ) + .join("\u2013") || null return (
- {displayName && {displayName}} - {displayUnit && displayUnit.length > 1 && ( - {displayUnit} + {label && {label}} + {unit && unit.length > 1 && ( + {unit} )}