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

feat(partition): treemap group text in grooves #652

Merged
merged 11 commits into from
Apr 30, 2020
Merged

Conversation

monfera
Copy link
Contributor

@monfera monfera commented Apr 27, 2020

Summary

  • Puts treemap text for groups into top grooves
  • Treemap texts are left-aligned and brought to top (groove texts are on the bottom)
  • Font min/max sizes can be configured per Layer

To limit areal distortion, the groove heights are capped by a proportion of the area.

image

Closes #611
Fixes the treemap part of #599
Ticks a few boxes in #612

Further iteration ideas:

  • expose constraints via configurability, eg. maximal area distortion
  • adherence to text padding - now it exploits maximum area

Checklist

Delete any items that are not applicable to this PR.

  • Any consumer-facing exports were added to src/index.ts (and stories only import from ../src except for test data & storybook)
  • This was checked for cross-browser compatibility, including a check against IE11
  • Proper documentation or storybook story was added for features that require explanation or tutorials
  • Unit tests were updated or added to match the most common scenarios

@monfera monfera self-assigned this Apr 27, 2020
Copy link
Member

@markov00 markov00 left a comment

Choose a reason for hiding this comment

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

Code wise LGTM. Tested locally on storybook and it works great.
I've some minor thing to notice:

  • the groove text is slightly horizontally misaligned if compared with its first rectangle text, I think we should use the same padding as the the sublayer

Screenshot 2020-04-28 at 15 42 29

- as already specified on the comments, I think we should provide at least one simple way to opt-out from the groovetext, exposing the `topGroove` parameter is the simplest way to do this, or a simple boolean (on/off) is fine on the config.

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.

Looks great Robert! Love the new options.

I only have two comments about the code.

Comment on lines 197 to 201
verticalAlignment === VerticalAlignments.top
? -(container.y0 + linePitch * rowIndex + padding + fontSize * overhang)
: verticalAlignment === VerticalAlignments.bottom
? -(container.y1 - linePitch * (totalRowCount - 1 - rowIndex) - fontSize * overhang)
: -((container.y0 + container.y1) / 2 + (linePitch * (rowIndex - totalRowCount)) / 2);
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is fine for this PR, but nested ternarys are screaming to be a separate function. Makes it so much cleaner and easier to read. 😱

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oops, meant to break it up, thanks for spotting this

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I extracted it out into a function with switch / case

1 file changed, 31 insertions(+), 7 deletions(-)

and while there are best practices that morph into rules with broad community approval, eg. don't nest ternaries, I'm not sure if it makes the code much more readable, at least I personally don't mind short, chained ternaries, they're easier for me to read than esp.

let rowCentroidY = null; 
if(....) {
  rowCentroidY = ....
} else if { 
.
.
.

because here there's no guarantee that something else further down doesn't modify the let binding.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done in 6d3acea

});

/** @internal */
export type VerticalAlignment = CanvasTextBaseline & $Values<typeof VerticalAlignments>;
Copy link
Collaborator

Choose a reason for hiding this comment

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

This kind of combined type is confusing. I think these should be separate types. This implies that the value VerticalAlignments has the same types as the VerticalAlignments which is not the case.

Fro example VerticalAlignments object does not have 'alphabetic' as a possible value.

Suggested change
export type VerticalAlignment = CanvasTextBaseline & $Values<typeof VerticalAlignments>;
export type VerticalAlignment = $Values<typeof VerticalAlignments>;
export type AllVerticalAlignment = CanvasTextBaseline & VerticalAlignment;

Copy link
Contributor Author

@monfera monfera Apr 29, 2020

Choose a reason for hiding this comment

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

It can certainly be broken up eg.

type PermittedVerticalAlignments = $Values<typeof VerticalAlignments>;
export type VerticalAlignment = CanvasTextBaseline & PermittedVerticalAlignments;

which just lifts and names the $Values part. Would that be clearer code? Your suggestion is the same extraction but I don't follow the namings as AllVerticalAlignments seems to hint that it's a broader / union set, while the purpose of the & is to intersect the two sets. Also, both do not need to be exported, but maybe you have some non-local change in mind.

OK why the heck did I do this in the first place, ie. why not just the expected $Values<typeof VerticalAlignments>? The &-ing will not in fact remove values from $Values<typeof VerticalAlignments> (one is a proper subset of the other). The purpose is to show intent and assurance to the compiler and code reader that

  • values are expected to be directly digestible by the Canvas2 API without compile time type juggling or worse, runtime type guards, as it's directly channeled into a ctx.textBaseline so it better be of CanvasTextBaseline(*)
  • yet, as you say, we don't currently expose all the alignments

There is a larger, somewhat theme and it'd be great to talk about it on account of this, we touched on esp. text styling configurability superficially with @markov00 and it'd be opportune to use this as a small example.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

broken up, as mentioned, in a slightly different way in cb141a6

Copy link
Collaborator

@nickofthyme nickofthyme Apr 29, 2020

Choose a reason for hiding this comment

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

Yeah the AllVerticalAlignments was just an arbitrary name I cam up with.

The change in cb141a6 is close to what I was referring to but the key is that the object with the js values and the type should be called the same, that way ts can import the Type and Values as one import.

// also using this
type SupportedVerticalAlignments = $Values<typeof VerticalAlignments>;

// makes this look strange
const myThing: SupportedVerticalAlignments = VerticalAlignments.top

These values are basically the poor mans enum because tsc enums are not ideally transpiled (see elastic/kibana#62957 (comment)), with this thinking, your enum values in this case would be different than the enum type.

To me the below is the ideal way to defined such enums.

export const VerticalAlignments = Object.freeze({
  top: 'top' as 'top',
  middle: 'middle' as 'middle',	
  bottom: 'bottom' as 'bottom',
});
type VerticalAlignments = $Values<typeof VerticalAlignments>;

// then it becomes much clearer how the type and enum values relate
const myThing: VerticalAlignments = VerticalAlignments.top

Could be something to talk about today at the sync 🤷

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, the enum would have various weaknesses here, one of which here is that it's not some opaque thing I want here, but a subtype of CanvasTextBaseline which is a very real set of strings.

If I understand, your remaining ask is that the object and type be named identically; it's doable, though with a bit less directness here as there's the above mentioned goal of piggybacking on the CanvasTextBaseline type, in 9c30090

@monfera
Copy link
Contributor Author

monfera commented Apr 29, 2020

@markov00 on the horizontal misalignment between group and leaf labels: there's still a padding at the group level, but it's leftward a bit, because the group wraps all the leafs, and to cause space between groups, it's larger (btw. the large groove on the top is just an increase of this grooves, but the left, right and bottom grooves aren't zeros either).

It'd be good to further improve on the alignment but it could be a small, follow-up prioritized item as we can do multiple things here - currently I'm leaning toward changing the groove sizing such that the left group groove is zero and the right group groove is double of what it is now, but it needs a bit of t(h)in(er)king. An alternative is to add an extra constraint on the groove text box but that's some additional code path. Just offsetting the text would be a third option, but it'd feel like a hack (long text might protrude on the right) and the vertical alignment would be accidental.

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.

I made a note on the enum comment with one final tweak if you could fix that before merging. Otherwise, everything looks great!

@markov00 markov00 changed the title feat(Partition): treemap group text in grooves feat(partition): treemap group text in grooves Apr 30, 2020
@monfera monfera merged commit 304dd48 into master Apr 30, 2020
@monfera monfera deleted the groovy-text-squashed branch April 30, 2020 09:47
markov00 pushed a commit that referenced this pull request Apr 30, 2020
# [19.1.0](v19.0.0...v19.1.0) (2020-04-30)

### Features

* **partition:** treemap group text in grooves ([#652](#652)) ([304dd48](304dd48))
@markov00
Copy link
Member

🎉 This PR is included in version 19.1.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

@markov00 markov00 added the released Issue released publicly label Apr 30, 2020
AMoo-Miki pushed a commit to AMoo-Miki/OpenSearch-Dashboards that referenced this pull request Feb 10, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
released Issue released publicly
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Improved category labels for treemap
3 participants