Skip to content

feat: add chart baseline#502

Merged
hcopp merged 36 commits intomasterfrom
hunter/chart-baseline
Apr 22, 2026
Merged

feat: add chart baseline#502
hcopp merged 36 commits intomasterfrom
hunter/chart-baseline

Conversation

@hcopp
Copy link
Copy Markdown
Contributor

@hcopp hcopp commented Mar 13, 2026

What changed? Why?

This PR adds "baseline" to chart axes

The concept of "baseline" is that this is the base value that the chart stems from. By default it is 0, meaning bars rendered on the screen will start at 0 and go up or down towards their actual value:

While this had been working before, setting a custom baseline was not working, now it is possible

image

This works by fixing all area and bar components towards the baseline, and stacking also is in this same manner.

Stacking logic works as such

  1. For each value in a series, the difference between that value and baseline is considered
  2. If the value is above the baseline, it is added to the "positive" value for that stack, otherwise "negative"
  3. Sums are combined and the end result is shown with some going positive and some negative

This means that if we have a stack such as

series={[{ id: 'a', data: [4, -2, 3] }, { id: 'b', data: [5, 1, 2] }]}

With a baseline of 0 we'd get [{ positive: 9, negative: 0 }, { positive: 1, negative: -2}, { positive: 7, negative: 0 }]

With a baseline of 3 we'd get [{ positive: 3, negative: 0 }, { positive: 0, negative: 7 }, { positive: 0, negative: 1 }] - keep in mind these values are from "3", so a negative of "7" really equals -4.

image

Root cause (required for bugfixes)

When we added stacking to all series we didn't factor in that eliminated the ability to use 'baseline' on Area and Bar. This removes that functionality from affected components and brings in a new centralized baseline property which can be customized on axes (on regular charts this is for the y axis for horizontal layout charts it is the x axis.

UI changes

Mobile

image

For web see above screenshots.

Testing

How has it been tested?

  • Unit tests
  • Interaction tests
  • Pseudo State tests
  • Manual - Web
  • Manual - Android (Emulator / Device)
  • Manual - iOS (Emulator / Device)

Testing instructions

Illustrations/Icons Checklist

Required if this PR changes files under packages/illustrations/** or packages/icons/**

  • verified visreg changes with Terran (include link to visreg run/approval)
  • all illustration/icons names have been reviewed by Dom and/or Terran

Change management

type=routine
risk=low
impact=sev5

automerge=false

@cb-heimdall
Copy link
Copy Markdown
Collaborator

cb-heimdall commented Mar 13, 2026

✅ Heimdall Review Status

Requirement Status More Info
Reviews 1/1
Denominator calculation
Show calculation
1 if user is bot 0
1 if user is external 0
2 if repo is sensitive 0
From .codeflow.yml 1
Additional review requirements
Show calculation
Max 0
0
From CODEOWNERS 1
Global minimum 0
Max 1
1
1 if commit is unverified 0
Sum 1
CODEOWNERS ✅ See below

CODEOWNERS

Code Owner Status Calculation
ui-systems-eng-team 1/1
Denominator calculation
Additional CODEOWNERS Requirement
Show calculation
Sum 0
0
From CODEOWNERS 1
Sum 1

/**
* Whether to animate gradient changes.
*/
animate?: boolean;
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moving this to base props

);
})}
</linearGradient>
</motion.linearGradient>
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Support animations on gradient

},
{
price: '0.06',
price: '1173.74',
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixing a random bug I've been seeing with price

* Baseline value for the area.
* When set, overrides the default baseline.
*/
areaBaseline?: number;
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Baseline on Areas were broken so having this at the axis level should solve it.

@hcopp hcopp marked this pull request as ready for review April 21, 2026 04:48
```jsx live
function PriceRange() {
const candles = btcCandles.slice(0, 180).reverse();
const candles = [...btcCandles].reverse().slice(0, 180);
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was causing issues across the board since props would affect all other examples that use btcCandles.

<Gradient
animate={shouldAnimate}
gradient={gradient}
transition={transitions?.update ?? transition}
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are now animating transitions

@hcopp hcopp self-assigned this Apr 21, 2026
*
* @default 0 for value axes, undefined for category axes
*/
baseline?: number;
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This concept wouldn't be relevant for a polar chart.

const chartSeries = useMemo(() => {
return series?.map(
(s): Series => ({
id: s.id,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would it be simpler to just do {...s} here

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call, honestly not sure why we have this at all here... Will cleanup

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh wait we are removing values that are on AreaSeries but not on Series

Image

Technically we could just drop this and pass all to CartesianChart under the hood but across the board we are taking LineSeries, BarSeries, and AreaSeries and only passing in the props that are present on Series. I think it could be a good practice so no misc props end up in a spot they shouldn't be.

What do you think?

@hcopp hcopp merged commit 49e4484 into master Apr 22, 2026
35 of 37 checks passed
@hcopp hcopp deleted the hunter/chart-baseline branch April 22, 2026 19:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

3 participants