From 1e3aa9f4b3cc15637e68b4a9901af4cefb9f2832 Mon Sep 17 00:00:00 2001 From: Benjamin Leonard Date: Mon, 17 Feb 2025 16:25:07 +0000 Subject: [PATCH 1/3] Dynamic Y axis width --- app/components/TimeSeriesChart.tsx | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/app/components/TimeSeriesChart.tsx b/app/components/TimeSeriesChart.tsx index 6a8e060ae..e5349ec38 100644 --- a/app/components/TimeSeriesChart.tsx +++ b/app/components/TimeSeriesChart.tsx @@ -75,6 +75,12 @@ const textMonoMd = { fill: 'var(--content-quaternary)', } +// The length of a character in pixels at 11px with GT America Mono +// Used for dynamically sizing the yAxis. If this were to fallback +// the font would likely be thinner than the monospaced character +// and therefore not overflow +const TEXT_CHAR_WIDTH = 6.82 + function renderTooltip(props: TooltipProps, unit?: string) { const { payload } = props if (!payload || payload.length < 1) return null @@ -153,6 +159,15 @@ export default function TimeSeriesChart({ ? { domain: [0, maxY], ticks: getVerticalTicks(TICK_COUNT, maxY) } : undefined + // We get the longest label length and multiply that with our `TICK_CHAR_WIDTH` + // and add the extra space for the tick stroke and spacing + // It's possible to get clever and calculate the width using the canvas or font metrics + // But our font is monospace so we can just use the length of the text * the baked width of the character + const maxLabelLength = yTicks + ? Math.max(...yTicks.ticks.map((tick) => yAxisTickFormatter(tick).length)) + : 0 + const maxLabelWidth = maxLabelLength * TEXT_CHAR_WIDTH + 14 + // falling back here instead of in the parent lets us avoid causing a // re-render on every render of the parent when the data is undefined const data = useMemo(() => rawData || [], [rawData]) @@ -204,6 +219,7 @@ export default function TimeSeriesChart({ tickMargin={8} tickFormatter={yAxisTickFormatter} padding={{ top: 32 }} + width={maxLabelWidth} {...yTicks} /> {/* TODO: stop tooltip being focused by default on pageload if nothing else has been clicked */} From 74b69cb69c9e38945e7077e4762c6c151a1c9a11 Mon Sep 17 00:00:00 2001 From: Benjamin Leonard Date: Mon, 17 Feb 2025 16:34:48 +0000 Subject: [PATCH 2/3] Remove spacing and make tick size/margin explicit --- app/components/TimeSeriesChart.tsx | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/app/components/TimeSeriesChart.tsx b/app/components/TimeSeriesChart.tsx index e5349ec38..af9e55a3f 100644 --- a/app/components/TimeSeriesChart.tsx +++ b/app/components/TimeSeriesChart.tsx @@ -122,6 +122,8 @@ type TimeSeriesChartProps = { } const TICK_COUNT = 6 +const TICK_MARGIN = 8 +const TICK_SIZE = 6 /** Round `value` up to nearest number divisible by `divisor` */ function roundUpToDivBy(value: number, divisor: number) { @@ -166,7 +168,7 @@ export default function TimeSeriesChart({ const maxLabelLength = yTicks ? Math.max(...yTicks.ticks.map((tick) => yAxisTickFormatter(tick).length)) : 0 - const maxLabelWidth = maxLabelLength * TEXT_CHAR_WIDTH + 14 + const maxLabelWidth = maxLabelLength * TEXT_CHAR_WIDTH + TICK_SIZE + TICK_MARGIN // falling back here instead of in the parent lets us avoid causing a // re-render on every render of the parent when the data is undefined @@ -192,7 +194,7 @@ export default function TimeSeriesChart({ width={width} height={height} data={data} - margin={{ top: 0, right: 8, bottom: 16, left: 0 }} + margin={{ top: 0, right: 0, bottom: 16, left: 0 }} > Date: Mon, 17 Feb 2025 16:37:53 +0000 Subject: [PATCH 3/3] Need spacing on old cards --- app/components/TimeSeriesChart.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/components/TimeSeriesChart.tsx b/app/components/TimeSeriesChart.tsx index af9e55a3f..f20828f46 100644 --- a/app/components/TimeSeriesChart.tsx +++ b/app/components/TimeSeriesChart.tsx @@ -194,7 +194,7 @@ export default function TimeSeriesChart({ width={width} height={height} data={data} - margin={{ top: 0, right: 0, bottom: 16, left: 0 }} + margin={{ top: 0, right: hasBorder ? 16 : 0, bottom: 16, left: 0 }} >