feat(BarChart): anchor non-stacked bars at value 0 when 0 is in domain#129
Closed
jamesxu-lightspark wants to merge 1 commit intomainfrom
Closed
feat(BarChart): anchor non-stacked bars at value 0 when 0 is in domain#129jamesxu-lightspark wants to merge 1 commit intomainfrom
jamesxu-lightspark wants to merge 1 commit intomainfrom
Conversation
Non-stacked bar charts on signed data (e.g. net = inflow - outflow) used to draw every bar from the bottom of the plot area up to its value, so negative values produced large bars hugging the lower edge instead of short bars hanging below the zero line. Anchor each bar at clamp(0, yMin, yMax) so: - All-positive data: anchor = yMin (bottom) — same as before. - Mixed signs: anchor = 0; positive bars grow up, negative bars grow down. - All-negative data: anchor = yMax (top); bars hang down to value. Same treatment applied to the horizontal orientation. Stacked path is unchanged (cumulative semantics already differ).
b48d9de to
b516235
Compare
Author
|
@greptile review |
Author
|
Closing — went with a recharts-based renderer in lighthouse instead of waiting on Origin. Leaving this here as a reference for the eventual Origin-side fix; once it lands, lighthouse can drop the recharts branch and consolidate back to OriginChart.Bar. |
Author
|
Reopening — keeping this open as the proper long-term fix. Lighthouse currently bridges via a small recharts-based SignedBarChart for the signed-bar use case, but the plan is to drop that bridge and use Origin directly once this lands. |
coreymartin
approved these changes
May 1, 2026
Author
|
Moved to the new monorepo per @coreymartin: https://github.com/lightsparkdev/webdev/pull/26977 |
lightspark-copybara Bot
pushed a commit
to lightsparkdev/js-sdk
that referenced
this pull request
May 1, 2026
…n domain (#26977) ## What Small change to BarChart so signed-value bars anchor at the zero line — negatives hang down, positives grow up — instead of all rendering from the plot bottom. Sheets, Looker, d3 defaults, and recharts all do this; Origin was the odd one out. For each non-stacked bar we compute `anchor = clamp(0, yMin, yMax)` and draw between `anchor` and the value: - **All-positive data** — anchor lands at `yMin` (bottom). Visual identical to before. - **Mixed signs** — anchor is `0`. Positives grow up, negatives hang down. - **All-negative data** — anchor lands at `yMax` (top). Bars hang down to their value. Same treatment applied to the horizontal orientation. Stacked path is intentionally untouched — cumulative semantics already differ from the simple value→height mapping. ## Why Came up while building a daily net inflow/outflow bar chart in lighthouse — the chart's domain spanned negative values, but every red bar was rendered from the bottom of the plot area up to the value, which made small negative days look as severe as the worst negative day. ## Not a breaking change - No API change — no props added, removed, or retyped. - All-positive data renders pixel-identical (`clamp(0, yMin, yMax) = yMin` when yMin is 0). - Only diffs are mixed-sign and all-negative charts, which were arguably broken before this. ## Notes - Originally proposed against the old origin repo at lightsparkdev/origin#129; moved here per @coreymartin. - Lighthouse currently has a small recharts-based bar chart bridging the signed-data case ([lighthouse#383](lightsparkdev/lighthouse#383)). Plan is to drop that bridge and use Origin directly once this lands. ## Test plan - [ ] Existing storybook bar charts (all-positive) render identically — visual diff is a no-op. - [ ] Mixed-sign story: bars cross the zero line cleanly. - [ ] Horizontal orientation: bars extend left of the zero column for negatives. - [ ] Stacked path unchanged. GitOrigin-RevId: 807866e8c7aa64e986b8b31f370630e162cabb6c
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Non-stacked bar charts now anchor at the zero line when the y-domain spans both positive and negative values. Negative bars hang below 0; positive bars grow up from 0.
Before this change, every bar was drawn from the bottom of the plot area up to its value — so a small negative number on a chart whose y-axis went from –150k to +100k rendered as a near-full-height bar instead of a short stub below 0. Pretty much every other charting tool (Sheets, Looker, d3 defaults, recharts) anchors at 0 for signed data, so this brings Origin in line with that expectation.
How it works
For each bar, we compute
anchor = clamp(0, yMin, yMax)and draw the bar betweenanchorand the value:yMin(the bottom), so the visual is identical to before.0— positive values grow up, negatives hang down.yMax(the top), so bars hang down to their value.The same treatment applies to the horizontal orientation. The stacked rendering path is intentionally untouched — cumulative bars already have their own semantics that differ from the simple
value → heightmapping.Why now
Came up while building a daily net inflow/outflow bar chart in lighthouse. The chart was rendering with all bars anchored at the plot bottom, which made small negative days look as dramatic as the worst negative day. Fixing it at the Origin layer makes every consumer get the right behaviour for free.
Test plan