From 6961c7ef41f4ca7744def1fff28b1b15bea15c5c Mon Sep 17 00:00:00 2001 From: Guillem Arias Fauste Date: Thu, 4 Jun 2026 22:19:38 +0200 Subject: [PATCH] =?UTF-8?q?fix(ds):=20chart=20flat-state=20=E2=80=94=20hai?= =?UTF-8?q?rline=20trendline,=20not=20a=20bisecting=20rule=20(#2137)=20(#2?= =?UTF-8?q?150)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Accounts with a flat series (a single valuation or an unchanged balance, where dataMin === dataMax) plotted the centered horizontal trendline at the full 2px stroke — a near-black full-bleed rule bisecting the hero card in light, leaving ~half the card a void (dark read it as an acceptable hairline). Detect the flat case (_isFlatSeries) and draw the line as a faint hairline (stroke-width 1, stroke-opacity 0.4) so it reads as "no change", consistent across light + dark. Verified on the Car Loan account (30D, no change): the heavy rule is gone. --- .../controllers/time_series_chart_controller.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/app/javascript/controllers/time_series_chart_controller.js b/app/javascript/controllers/time_series_chart_controller.js index 1bf6f8d89..1b8d67254 100644 --- a/app/javascript/controllers/time_series_chart_controller.js +++ b/app/javascript/controllers/time_series_chart_controller.js @@ -140,7 +140,18 @@ export default class extends Controller { .attr("d", this._d3Line) .attr("stroke-linejoin", "round") .attr("stroke-linecap", "round") - .attr("stroke-width", this.strokeWidthValue); + // A flat series (no variation across the period — a single valuation or an + // unchanged balance) otherwise renders as a full-bleed near-black rule + // bisecting the hero card. Draw it as a faint hairline so it reads as + // "no change", consistent across light and dark (#2137). + .attr("stroke-width", this._isFlatSeries ? 1 : this.strokeWidthValue) + .attr("stroke-opacity", this._isFlatSeries ? 0.4 : 1); + } + + get _isFlatSeries() { + const min = d3.min(this._normalDataPoints, this._getDatumValue); + const max = d3.max(this._normalDataPoints, this._getDatumValue); + return min === max; } _installTrendlineSplit() {