Skip to content

fix: keep Y-axis ticks evenly spaced when Recharts thins them for overlap - #3172

Open
arj22 wants to merge 26 commits into
hyperdxio:mainfrom
arj22:anudeep/y-axis-uneven-tick-spacing
Open

arj22 wants to merge 26 commits into
hyperdxio:mainfrom
arj22:anudeep/y-axis-uneven-tick-spacing

Conversation

@arj22

@arj22 arj22 commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

Fixes uneven spacing between Y-axis ticks (e.g. 0, 300, 1k instead of 0, 250, 500, 750, 1k) on an otherwise linear axis.

Screenshot 2026-09-21 at 10 07 00 PM Screenshot 2026-09-21 at 10 07 06 PM

Recharts picks its own tick values, then drops some to avoid overlapping labels on shorter charts — but it drops them without re-spacing the rest, which is what causes the unevenness. This feeds it evenly-spaced candidates instead, so whatever survives stays evenly spaced. Same number of ticks as before, just positioned correctly.

🤖 Generated with Claude Code

…rlap

Recharts' own "nice" tick candidates aren't always uniformly spaced, and
its minTickGap-based overlap thinning drops individual candidates
without re-spacing the survivors - producing axes like 0/300/1k
(gaps of 300 then 700) instead of 0/250/500/750/1k.

Feed it a uniform candidate set instead: thinning a uniformly-spaced
sequence for overlap always keeps every Nth candidate, so whatever
survives stays evenly spaced. Tick count behavior is unchanged - this
only changes which values are chosen, not how many survive.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@changeset-bot

changeset-bot Bot commented Sep 22, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 3e7dc0e

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
@hyperdx/app Patch
@hyperdx/api Patch
@hyperdx/otel-collector Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercel Bot commented Sep 22, 2026

Copy link
Copy Markdown

@arj22 is attempting to deploy a commit to the HyperDX Team on Vercel.

A member of the Team first needs to authorize it.

@greptile-apps

greptile-apps Bot commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 5/5

The PR appears safe to merge; the latest change correctly includes the fixed zero edge of BELOW alert areas when calculating the Y-axis domain.

Summary

This PR replaces Recharts-generated Y-axis candidates with clean, evenly spaced ticks while preserving fallback behavior for stacked, degenerate, reference-line, and precision-constrained charts.

  • Adds tick-step selection, label-distinctness checks, precision escalation, and explicit Y-axis bound calculation.
  • Propagates alert reference values through chart wrappers so ticks account for rendered threshold areas.
  • Adds regression coverage for spacing, formatting, stacked data, negative ranges, reference lines, and alert threshold variants.
  • Updates compact duration formatting to support explicit precision escalation.
Diagram
%%{init: {'theme': 'neutral'}}%%
flowchart LR
  A[Chart data and visible series] --> B[computeYAxisBounds]
  C[Alert reference values] --> B
  D[Axis number format] --> B
  B --> E{Automatic fallback required?}
  E -->|Stacked, empty, or degenerate| F[Recharts automatic domain and ticks]
  E -->|Concrete range| G[Generate nearby nice steps]
  G --> H[Reject excess, collapsed, duplicate, or oversized labels]
  H --> I[Domain, evenly spaced ticks, and formatter]
  I --> J[Recharts YAxis]
Loading

Reviews (23) · Last reviewed commit: "Include the fixed 0 edge for BELOW alert..."

Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx Outdated
@github-actions

github-actions Bot commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

Deep Review

No critical issues found. This PR is well-iterated (26 commits, 22 prior review rounds) and the previous-comments reviewer confirms every prior substantive thread — stacked-bar total clipping, 2.5-step density, the maxTicks overflow cap, float-dust cleanup, degenerate-domain fallbacks, and stale thresholdMax widening — is genuinely resolved in the current code. Correctness and performance reviewers found no defects. Two P2 items and a few nits below.

🟡 P2 — recommended

  • packages/app/src/HDXMultiSeriesTimeChart.tsx:1227 — Reference-line values bypass the finiteness filter that scanYAxisValueRange applies to data, so a non-finite or empty threshold reaches the extend-domain branch and produces a [NaN, NaN] domain with NaN ticks, blanking the axis while an alert threshold is mid-edit (fit-to-data or a series selection active); getAlertReferenceLineValues guards only threshold == null, and the getExpandableYAxisTicks finite guard hands off to getYAxisTicks, which has none.
    • Fix: Filter referenceLineValues to finite numbers before spreading into Math.min/Math.max, and reject non-finite values in getAlertReferenceLineValues.
  • packages/app/src/utils.ts:1103 — The new precision parameter on formatDurationMsCompact has no direct unit test; its µs (ms < 1) and ms (ms < 1000) precision branches are exercised only indirectly through a distinctness assertion whose values land in the hours branch, so a wrong significant-digit count that still yields distinct labels would pass.
    • Fix: Add exact-string assertions for formatDurationMsCompact with an explicit precision across the ns/µs/ms/s/m/h branches.
🔵 P3 nitpicks (4)
  • packages/app/src/HDXMultiSeriesTimeChart.tsx:1058getExpandableYAxisTicks re-implements the entire step-scan core of getNiceYAxisTicks (finite guard, niceStepsNear, step loop, ticksWithinRange, the verbatim < 2 / > maxTicks guard, resolveDistinctTickLabels), so a future change to the tick-selection rule must be applied in two places or the branches silently diverge.
    • Fix: Extract a shared scanForNiceStep helper returning { step, ticks, formatter } and layer only the expansion logic on top.
  • packages/app/src/HDXMultiSeriesTimeChart.tsx:1147 — The getYAxisTicks fallback block (build baseFormat, return { domain, ticks, tickFormatter }) is repeated verbatim across all three branches of computeYAxisBounds, a drift hazard in an already-long function.
    • Fix: Extract a single reduceTickCountFallback(lower, upper, axisNumberFormat) helper and call it from each fallback site.
  • packages/app/src/HDXMultiSeriesTimeChart.tsx:1109 — The new exported helpers scanYAxisValueRange and computeYAxisBounds type graphResults as any[], spreading an untyped surface into new public API; accesses are runtime-guarded and it mirrors the pre-existing MemoChart prop, so it is not a regression, but it violates the project's documented any guidance on new lines.
    • Fix: Type the parameter as Record<string, unknown>[] (or a shared row type) to keep any from propagating to future callers.
    • project-standards, kieran-typescript
  • packages/app/src/components/Alerts.tsx:271getAlertReferenceLineValues guards if (threshold == null) on a parameter typed as a required non-nullable number, so the branch is dead per the types and also fails to catch the NaN/empty runtime value behind the P2 above.
    • Fix: Replace the null check with a Number.isFinite(threshold) guard so the type and runtime intent agree.

Reviewers (10): correctness, adversarial, testing, maintainability, project-standards, performance, kieran-typescript, previous-comments, agent-native, learnings-researcher.

Testing gaps:

  • No test drives computeYAxisBounds with non-finite or empty-string referenceLineValues in the selection/fit-to-data branch (the axis-poisoning path).
  • No test covers referenceLineValues in the fit/selection branch with flat (all-equal) data, where the extend branch is short-circuited and the threshold line is dropped from axis sizing.
  • No test exercises the referenceLineValues={undefined} path relying on the EMPTY_REFERENCE_LINE_VALUES default at the MemoChart boundary.

No finding blocks merge automatically. A maintainer will expect P0/P1 findings in code this PR changes to be fixed; P2/P3 are your call -- fix or reply. Never fix findings about surrounding code here; reply instead. Do not widen the PR. How to respond

Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx Outdated
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx Outdated
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx Outdated
Comment thread packages/app/src/__tests__/HDXMultiSeriesTimeChart.test.ts Outdated
@github-actions

github-actions Bot commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

PR Review

If you are a coding agent acting for the author, read this first.
Nothing below blocks merge automatically; a maintainer decides. What they will expect:

  • 🔴 critical or 🟠 major in code this PR adds or changes: fix before asking for review.
  • 🔵 minor in code this PR changes: your call. Fix if small, otherwise reply.
  • Anything about surrounding code, or asking you to widen the change (hoist a helper,
    dedupe with another file, fix other call sites): never fix here, whatever the
    severity. Reply with one sentence; if it is critical, say so plainly so a human sees it.

One commit per review round. After two rounds, stop and ask a maintainer to review
scope rather than addressing more automated findings. Full rule: AGENTS.md.

5 finding(s): 🔴 0 critical · 🟠 0 major · 🔵 5 minor

5 posted as inline comment(s) on the changed lines.


Severity is the reviewer's own estimate and is used for ordering, not filtering. No finding blocks merge automatically; a maintainer decides.

Three review findings addressed:

Critical: the new default-domain max was computed from the largest
individual series value, but stacked bars sum at each timestamp (all
share stackId="1") - a 60+40 stack reached 100 but got a domain top of
63. Stacked bars now defer to Recharts entirely, as before this PR.

Major: dividing an unrounded domain (max * 1.05, or max + padding) into
even quarters produced fractional labels (341/683/1k) or, worse,
duplicate rounded ones (a peak of 3 gave 0/1/2/2/3). Ported the
Graphics Gems "nice number" rounding already used by the CLI's
termchart (packages/cli/src/termchart/scale.ts's niceTicks) so the
domain rounds to a clean step before ticks are chosen from it.

Minor: consolidated the two near-identical min/max scans (default vs.
selection/fit-to-data) into one scanYAxisValueRange, parameterized by
a visibility predicate, and replaced a tautological test (asserting an
arithmetic sequence has equal gaps, which can't fail) with real
domain/tick assertions for the reported peaks.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx Outdated
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx Outdated
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx Outdated
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx Outdated
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx Outdated
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx Outdated
arj22 and others added 2 commits September 21, 2026 22:46
scaling, and the 2.5 step

Four issues from this round's review:

Critical/P1 (duplicate reports): the stacked-bar guard only sat inside
the no-selection branch, so a stacked bar WITH an active legend
selection still fell through to per-series-max scanning. Moved the
guard to the top of computeYAxisBounds so it applies unconditionally.

Critical: getNiceYAxisBounds(0, 0) (all-zero data) or a negative max
past its max<=min guard produced a literal [0, 0] or inverted [0, -5]
domain instead of falling back - toYAxisBounds now falls back to each
branch's own no-data sentinel ([0,'auto'] default, ['auto','auto']
fit-to-data) whenever the guard fires.

Major: the max scan used the full lineData (up to 250 materialized
series) instead of visibleLineData (selection- and
HARD_LINES_LIMIT-filtered, i.e. what's actually drawn), so an
undrawn series could scale the axis and squash the real lines to the
bottom of the plot. Also let scanYAxisValueRange drop its now-unneeded
isVisible predicate, since visibleLineData is already filtered.

Major: the nice-step algorithm's 2.5 bucket produced ticks (e.g.
12.5) that formatAxisTick rounds to integers past its magnitude
threshold ("13"), breaking the even progression this PR exists to
fix. Dropped 2.5, matching the existing 1/2/5-only precedent in
components/TimelineChart/utils.ts's calculateInterval.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Missed the toPrecision(12) cleanup the CLI's niceTicks (which this was
ported from) already does - a 0.1-ish step could emit a tick like
0.6000000000000001 or a domain endpoint with the same dust.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx Outdated
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx Outdated
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx Outdated
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx Outdated
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx Outdated
arj22 and others added 2 commits September 22, 2026 00:07
Nice-rounding ticks by expanding the domain regressed Fit-Y-Axis-to-Data
(halved its effective zoom), added dead space/lost ticks on the default
axis, and went stale once an alert reference line silently extends the
domain. Ticks are now chosen within the existing (unexpanded) domain
instead, and are skipped in favor of Recharts' own when a reference line
is present. Also restores 2.5 as a valid step everywhere except the one
magnitude where it produces non-integer ticks.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
A selection with fit-to-data off degenerated to the unpinned fit
fallback (['auto','auto']) instead of the zero-pinned default, since
only fitting itself should opt out of the zero baseline.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx Outdated
Rounding to the nearest 1/2/2.5/5 step could pick one smaller than the
raw target, overflowing past maxTicks (e.g. 6 ticks for a 0-1480
range). Now searches nearby nice steps and picks the smallest one
whose actual generated ticks still fit the limit.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx Outdated
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx Outdated
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx Outdated
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx
Recharts widens an explicit domain to fit out-of-range data
(allowDataOverflow defaults to false), so a domain pinned at
[0, upperBound] with negative data actually renders wider than that,
stranding a domain-only tick list in a sliver at the top of the axis.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx Outdated
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx Outdated
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx Outdated
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx Outdated
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx Outdated
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx
max * 1.05 made the upper bound more negative than max itself for an
all-negative series (-900 * 1.05 = -945), excluding the data's own
maximum from the domain and stranding the precomputed ticks once
Recharts widened the rendered domain back up to it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx Outdated
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx Outdated
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx Outdated
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx
- Reference lines: an explicit numeric domain skips Recharts' own nice
  rounding even with ticks suppressed, reproducing the exact uneven
  spacing this PR fixes on every alert chart. Fall back to auto
  entirely when a reference line is present.
- Selection branch: mirror the default branch's negative-data fix -
  the lower bound must follow negative data regardless of fit mode,
  since Recharts widens the domain to it either way.
- Reject any candidate step whose formatted labels collide (e.g. 1500
  and 2000 both rendering "2k"), not just the literal 2.5 step.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx Outdated
Comment thread packages/app/src/__tests__/HDXMultiSeriesTimeChart.test.ts
Comment thread packages/app/src/__tests__/HDXMultiSeriesTimeChart.test.ts Outdated
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx
cleanNumber's 12-significant-digit rounding can make t + step round
back to t once |t| is large enough relative to step, so the loop's
increment silently stopped advancing while still pushing to the ticks
array - a frozen tab followed by OOM, reachable from the selection/fit
branch's flat-high-baseline case.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx Outdated
Grafana/Chronosphere never render two ticks with the same label - a
narrow range at the configured decimal precision (e.g. a 2.9-3.4GB
memory gauge at 0 decimals) collapsed every tick to "3 GB", or worse,
a single tick with no scale at all.

Tick selection now escalates past the configured mantissa (bypassing
formatAxisTick's own forced-0 rule) when that's the only way to keep
labels distinct, applied uniformly to the default and Fit-to-Data/
selection branches alike. A candidate step or expansion is now also
rejected outright if it would leave fewer than 2 ticks - a one-tick
axis is never an acceptable outcome, even though its label is
trivially "distinct" from nothing.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx Outdated
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx Outdated
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx Outdated
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx
- Duration formats had no escalation path at all - a colliding range
  (e.g. 3600-3700s all rendering "1h") fell back to null/undefined
  ticks unconditionally. Now escalates formatDurationMsCompact's fixed
  2-3 significant digits the same way numeric formats do.
- Numeric escalation started from "configured mantissa + 1", but
  formatAxisTick already forces mantissa to 0 above its magnitude
  threshold regardless of what's configured - so the collision was at
  0, and escalating from e.g. 3 (mantissa 2 + 1) skipped a sufficient
  1, producing needlessly wide labels that can overflow the axis
  width budget. Escalation now always starts at 1.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx
Comment thread packages/app/src/__tests__/HDXMultiSeriesTimeChart.test.ts
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx Outdated
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx
arj22 and others added 2 commits September 22, 2026 18:24
Escalating precision to keep ticks distinct could render a label wider
than the axis leaves room for; now rejected in favor of a coarser step,
scoped to number/percent since byte/duration were already exempt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…en-tick-spacing

# Conflicts:
#	packages/app/src/HDXMultiSeriesTimeChart.tsx
#	packages/app/src/__tests__/HDXMultiSeriesTimeChart.test.ts
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx Outdated
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx Outdated
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx Outdated
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx Outdated
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx Outdated
Fixed-unit escalation no longer reintroduces the suffix formatAxisTick
drops (P1); escalated numeric labels now trim trailing zeros like the
base formatter; duration escalation now respects the label budget too,
reusing a parameterized formatDurationMsCompact instead of a duplicate;
the default-axis branch defers to Recharts fully (not a raw domain) when
no step fits; yAxisBounds memoizes on a boolean, not the referenceLines
node identity.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx Outdated
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx
Comment thread packages/app/src/utils.ts
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@arj22
arj22 force-pushed the anudeep/y-axis-uneven-tick-spacing branch from b3bed8f to f32ee39 Compare September 23, 2026 02:03
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx Outdated
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx
Comment thread packages/app/src/__tests__/HDXMultiSeriesTimeChart.test.ts
Comment thread packages/app/src/utils.ts
computeYAxisBounds was leaving ticks undefined when its nice-step
search came up empty, deferring to Recharts' raw domain-division
default - which has no distinctness guard and can render duplicate
labels. Falls back to getYAxisTicks's reduce-tick-count strategy
instead, restoring behavior hyperdxio#3162 already shipped for this case
before the merge replaced its wiring. Also trims a few comments
that crept past 2 lines.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx Outdated
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx Outdated
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx Outdated
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx
… step

Full-precision fallback now respects the label budget like every other
escalation path, falling through to a coarser step instead of rendering
overflowing grouped numbers. Reference-line domains now dedup ticks via
getYAxisTicks instead of dropping tick management entirely, restoring
behavior alert charts had before this branch existed. The 2.5x10^n step
exclusion now applies at every magnitude below 1 (0.25, 0.025, ...), not
just the bare value - those round unevenly the same way.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx Outdated
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx
Comment thread packages/app/src/__tests__/HDXMultiSeriesTimeChart.test.ts
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx
@arj22

arj22 commented Sep 23, 2026

Copy link
Copy Markdown
Contributor Author

@brandon-pereira @pulpdrew this is ready for review.

Here's a brief overview of changes

Screenshot 2026-09-23 at 3 55 19 AM Screenshot 2026-09-23 at 3 55 25 AM Screenshot 2026-09-23 at 3 55 31 AM Screenshot 2026-09-23 at 4 32 41 AM Screenshot 2026-09-23 at 4 50 36 AM

Note: The following one is a pre-existing issue, just reachable through one more path now. Only surfaces on Fit-to-Data/legend-isolated tiles with near-flat data, e.g. a 99.995%–99.997% success-rate panel.
Screenshot 2026-09-23 at 3 55 45 AM

…nce lines

Mantissa-aware 2.5x10^n exclusion: only excluded below 1 when the format
forces integers, restoring tick density for decimal gauges/ratios that
have room to represent it exactly (e.g. mantissa 2 keeps a clean 0.25
step instead of falling back to a sparser 0.5 one).

Reference lines: threaded real threshold value(s) from Alerts.tsx down
through DBTimeChart/MemoChart into computeYAxisBounds (previously just a
boolean), so a threshold that would widen the domain gets folded into
the nice-step calculation up front instead of ticking a domain that
goes stale once Recharts' ifOverflow="extendDomain" moves it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Comment thread packages/app/src/components/AlertPreviewChart.tsx
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx
Comment thread packages/app/src/components/alerts/AlertDetailChart.tsx
Comment thread packages/app/src/__tests__/HDXMultiSeriesTimeChart.test.ts
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx
…erts

getAlertReferenceLineValues mirrors getAlertReferenceLines' own branching
so the values used to size the Y-axis domain can never include a
thresholdMax that isn't actually rendered - previously any non-null
thresholdMax was grabbed unconditionally, so a leftover value from an
alert that used to be BETWEEN/NOT_BETWEEN (but was since changed to a
simple type) could silently stretch the domain around an invisible line.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Comment thread packages/app/src/components/Alerts.tsx
Comment thread packages/app/src/__tests__/HDXMultiSeriesTimeChart.test.ts
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx
getAlertReferenceLineValues omitted the implicit y1=0 edge that
getAlertReferenceLines draws for BELOW/BELOW_OR_EQUAL, letting the
Y-axis domain get computed too narrow and then silently widened.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Comment thread packages/app/src/components/Alerts.tsx
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx
Comment thread packages/app/src/__tests__/HDXMultiSeriesTimeChart.test.ts
Comment thread packages/app/src/components/Alerts.tsx
Comment thread packages/app/src/HDXMultiSeriesTimeChart.tsx

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant