Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: improved heatmap legend #1317

Merged
merged 8 commits into from Aug 19, 2021

Conversation

markov00
Copy link
Member

Summary

The heatmap legend now shows the full ranges configured, to improve its readability when using a categorical/band scale.

BREAKING CHANGE

The <Heatmap> API is changed: the color scale configuration is self-contained into the colorScale prop. The ranges and colors are now described as ColorBand objects, where a color is associated with a start and end values.
The heatmap is currently marked as @alpha so the breaking change will not be propagated as a major version bump.

all-test-ts-baseline-visual-tests-for-all-stories-heatmap-alpha-categorical-visually-looks-correct-1-snap

Details

colors, ranges and colorScale props are now replaced by

colorScale: HeatmapBandsColorScale;

/** @alpha */
export type ColorBand = {
  start: number;
  end: number;
  color: Color;
  label?: string;
};

/** @alpha */
export interface HeatmapBandsColorScale {
  type: 'bands';
  bands: Array<ColorBand>;
  /** called on ColorBands without a provided label */
  labelFormatter?: (start: number, end: number) => string;
}

Checklist

  • The proper chart type label was added (e.g. :xy, :partition) if the PR involves a specific chart type
  • The proper feature label was added (e.g. :interactions, :axis) if the PR involves a specific chart feature
  • Any consumer-facing exports were added to packages/charts/src/index.ts (and stories only import from ../src except for test data & storybook)
  • Proper documentation or storybook story was added for features that require explanation or tutorials

@markov00 markov00 added :legend Legend related issue :heatmap Heatmap/Swimlane chart related issue labels Aug 19, 2021
@markov00 markov00 added the enhancement New feature or request label Aug 19, 2021
Copy link
Collaborator

@nickofthyme nickofthyme left a comment

Choose a reason for hiding this comment

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

LGTM

@@ -1,7 +1,7 @@
{
"name": "@elastic/charts",
"description": "Elastic-Charts data visualization library",
"version": "34.0.0",
"version": "34.0.0a",
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
"version": "34.0.0a",
"version": "34.0.0",

Copy link
Member Author

Choose a reason for hiding this comment

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

done 7a85eef

bands: [
{ color: '#ca0020', start: -5, end: -3 },
{ color: '#f4a582', start: -3, end: -1 },
{ color: 'rgb(206,206,206)', start: -1, end: 1 },
Copy link
Collaborator

Choose a reason for hiding this comment

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

⬛ 🐑

Copy link
Member Author

Choose a reason for hiding this comment

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

done 2fb4d76

Comment on lines 30 to 35
// filter out wrongly configured bands
if (start > end) {
return acc;
}
acc.push({ start, end, color, label: label ?? labelFormatter(start, end) });
return acc;
Copy link
Contributor

Choose a reason for hiding this comment

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

instead of the double return, would like the positive

// admit only proper bands
if(start < end) acc.push({ start, end, color, label: label ?? labelFormatter(start, end) });
return acc;

Copy link
Member Author

Choose a reason for hiding this comment

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

done 2fb4d76

Comment on lines +39 to +40
const scale = getBandScale(bands);
return { scale, bands };
Copy link
Contributor

Choose a reason for hiding this comment

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

Instead of cramming in the scale too, thus turning a simpler return type into a deeper tuple (object), the bands could be computed separately where getBandsColorScale is also used (lower coupling)

Copy link
Member Author

Choose a reason for hiding this comment

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

linking your next comment #1317 (comment)

Comment on lines +43 to +53
function getBandScale(bands: ColorBand[]): ColorScale {
return (value) => {
for (let i = 0; i < bands.length; i++) {
const { start, end, color } = bands[i];
if (start <= value && value < end) {
return color;
}
}
return TRANSPARENT_COLOR;
};
}
Copy link
Contributor

Choose a reason for hiding this comment

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

This is great for this PR and it's unlikely that there'll be hundreds of bands, though we could at some point harness our monotonicHillClimb (or derivative) for O(log n) as well as avoidance of a hand rolled loop

Copy link
Member Author

Choose a reason for hiding this comment

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

yep definitely, this should anyway be exported, improved and reused as band/categorical scale if we want

Comment on lines +22 to +25
export const getColorScale = createCustomCachedSelector([getHeatmapSpecSelector], (spec): {
scale: ColorScale;
bands: Required<ColorBand>[];
} => getBandsColorScale(spec.colorScale));
Copy link
Contributor

Choose a reason for hiding this comment

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

Ah okay you handle these together in the selector, that's why you wanted to bundle them

Copy link
Member Author

Choose a reason for hiding this comment

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

exactly

Copy link
Contributor

@monfera monfera left a comment

Choose a reason for hiding this comment

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

LGTM, also tried with edge cases: 1 band, 0 bands, 1 band but wrong start-end order
And with incomplete coverage, eg. gap or leaving the lowest or highest part of the domain uncovered with legends

@markov00 markov00 merged commit 49c35ce into elastic:master Aug 19, 2021
@markov00 markov00 deleted the 2021_08_19-heatmap_legend branch August 19, 2021 17:48
nickofthyme pushed a commit that referenced this pull request Aug 19, 2021
# [34.1.0](v34.0.0...v34.1.0) (2021-08-19)

### Bug Fixes

* **goal:** tooltip actual color ([#1302](#1302)) ([dbe9d36](dbe9d36))
* **heatmap:** improve legend item ([#1317](#1317)) ([49c35ce](49c35ce))
* **legend:** no truncation with single value ([#1316](#1316)) ([7ec8a9f](7ec8a9f))

### Features

* **goal:** optional target tick ([#1301](#1301)) ([88adf22](88adf22))
@nickofthyme
Copy link
Collaborator

🎉 This PR is included in version 34.1.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

@nickofthyme nickofthyme added the released Issue released publicly label Aug 19, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request :heatmap Heatmap/Swimlane chart related issue :legend Legend related issue released Issue released publicly
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants