From bf21e720dc565244bdf885195f5c2dc36ece5365 Mon Sep 17 00:00:00 2001 From: Neko Ayaka Date: Wed, 21 Oct 2026 06:29:57 +0800 Subject: [PATCH] fix(ui): render d3 axis ticks in the viewer font d3-axis sets font-family="sans-serif" on each axis group, so numeric tick labels used the system sans instead of Quicksand. Drop the attribute after each axis call so ticks inherit the page font. Co-Authored-By: Claude Opus 5.5 --- packages/ui/client/src/components/CaseCartesian.vue | 7 ++++++- packages/ui/client/src/components/ParallelCoordinates.vue | 5 +++++ packages/ui/client/src/components/ScatterMatrix.vue | 5 +++-- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/packages/ui/client/src/components/CaseCartesian.vue b/packages/ui/client/src/components/CaseCartesian.vue index 1153ba3..b8e3f1b 100644 --- a/packages/ui/client/src/components/CaseCartesian.vue +++ b/packages/ui/client/src/components/CaseCartesian.vue @@ -76,7 +76,12 @@ function drawDots(svg: Selection) { g.call((horizontal ? axisBottom(scale) : axisLeft(scale)).tickSizeOuter(0)) else g.call((horizontal ? axisBottom(scale) : axisLeft(scale)).ticks(horizontal ? 8 : 5).tickFormat(value => formatTick(value as number)).tickSizeOuter(0)) - g.call(group => group.selectAll('line, path').attr('stroke', 'var(--chart-grid)')) + // NOTICE: + // d3-axis writes `font-family="sans-serif"` (and `font-size="10"`) onto the axis group on every call, + // so tick labels would render in the system sans instead of the viewer font. Drop the attribute so + // the labels inherit `font.sans` from the page. See `node_modules/d3-axis/src/axis.js:109-110` (`selection.attr("font-family", "sans-serif")`). + g.attr('font-family', null) + .call(group => group.selectAll('line, path').attr('stroke', 'var(--chart-grid)')) .call(group => group.selectAll('text').attr('fill', 'var(--chart-text)').attr('font-size', 11)) if (axis.kind === 'category') { const picked = props.filters.categories[axis.name] diff --git a/packages/ui/client/src/components/ParallelCoordinates.vue b/packages/ui/client/src/components/ParallelCoordinates.vue index 439b5de..f19baef 100644 --- a/packages/ui/client/src/components/ParallelCoordinates.vue +++ b/packages/ui/client/src/components/ParallelCoordinates.vue @@ -193,7 +193,12 @@ function drawLines(svg: Selection) { return } const scale = scales.get(axis.name) as ScaleContinuousNumeric + // NOTICE: + // d3-axis writes `font-family="sans-serif"` (and `font-size="10"`) onto the axis group on every call, + // so tick labels would render in the system sans instead of the viewer font. Drop the attribute so + // the labels inherit `font.sans` from the page. See `node_modules/d3-axis/src/axis.js:109-110` (`selection.attr("font-family", "sans-serif")`). g.call(axisLeft(scale).ticks(5).tickFormat(value => formatTick(value as number)).tickSizeOuter(0)) + .attr('font-family', null) .call(axisGroup => axisGroup.selectAll('text').attr('fill', 'var(--chart-text)')) .call(axisGroup => axisGroup.selectAll('line, path').attr('stroke', 'var(--chart-grid)')) const brush = brushY().extent([[-12, margin.top], [12, height - margin.bottom]]).on('brush end', (event: { selection: [number, number] | null, sourceEvent?: Event }) => { diff --git a/packages/ui/client/src/components/ScatterMatrix.vue b/packages/ui/client/src/components/ScatterMatrix.vue index a1f751f..eef373f 100644 --- a/packages/ui/client/src/components/ScatterMatrix.vue +++ b/packages/ui/client/src/components/ScatterMatrix.vue @@ -174,11 +174,12 @@ function render(): void { if (box != null && box.x === columnMetric && box.y === rowMetric) group.call(behavior.move, [[xs(box.x0), ys(box.y1)], [xs(box.x1), ys(box.y0)]]) // Ticks only along the outer edge, so the cells stay readable. + // NOTICE: d3-axis sets `font-family="sans-serif"` on each axis group; removing it lets the ticks inherit the viewer font. if (column === 0) { - g.append('g').attr('transform', `translate(${pad - 3},0)`).call(axisLeft(ys).ticks(3).tickFormat(value => formatTick(value as number)).tickSize(3)).call(axisGroup => axisGroup.select('.domain').remove()).call(axisGroup => axisGroup.selectAll('text').attr('fill', 'var(--chart-text)')) + g.append('g').attr('transform', `translate(${pad - 3},0)`).call(axisLeft(ys).ticks(3).tickFormat(value => formatTick(value as number)).tickSize(3)).attr('font-family', null).call(axisGroup => axisGroup.select('.domain').remove()).call(axisGroup => axisGroup.selectAll('text').attr('fill', 'var(--chart-text)')) } if (row === count - 1) { - g.append('g').attr('transform', `translate(0,${cell - pad + 3})`).call(axisBottom(xs).ticks(3).tickFormat(value => formatTick(value as number)).tickSize(3)).call(axisGroup => axisGroup.select('.domain').remove()).call(axisGroup => axisGroup.selectAll('text').attr('fill', 'var(--chart-text)')) + g.append('g').attr('transform', `translate(0,${cell - pad + 3})`).call(axisBottom(xs).ticks(3).tickFormat(value => formatTick(value as number)).tickSize(3)).attr('font-family', null).call(axisGroup => axisGroup.select('.domain').remove()).call(axisGroup => axisGroup.selectAll('text').attr('fill', 'var(--chart-text)')) } })) paint()