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(annotations): marker body with dynamic positioning #1116

Merged
merged 19 commits into from
Apr 22, 2021

Conversation

nickofthyme
Copy link
Collaborator

@nickofthyme nickofthyme commented Apr 12, 2021

Summary

fixes #1040, fixes #1125

Adds a new render component markerBody on LineAnnotationSpec which is positioned using popper.js within the chart <canvas> area. markerBody and marker (i.e. the marker icon) are now able to render as ReactNode or a ComponentType<LineAnnotationDatum>. This allows for simple text or JSX components or a complex react component that is rendered with the LineAnnotationDatum as props. With these props one can render a marker icon or body based on values from the datum.

Screen.Recording.2021-04-19.at.04.38.49.PM.mp4

Note: The markerBody is only rendered when a marker (aka icon) is provided.

Refactoring notes:

  • Abstracted the marker logic from annotations into LineMarker component.
  • Create a eachRotation helper to DRY-up code for it.each<Rotation> logic where -90 in a png filename is converted to 90, unknowingly causing duplicated png file names to be overridden.
  • Add index to annotation id in the likely event there are multiple annotations with the same joined parameters as seen in the code below...
    export function getAnnotationLinePropsId(
    specId: string,
    datum: LineAnnotationDatum,
    index: number,
    verticalValue?: any,
    horizontalValue?: any,
    ) {
    return [specId, verticalValue, horizontalValue, datum.header, datum.details, index].join('__');
    }

Checklist

  • 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
  • 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

@nickofthyme nickofthyme added bug Something isn't working enhancement New feature or request :annotation Annotation (line, rect, text) related issue labels Apr 12, 2021
@@ -541,7 +558,7 @@ export function isDefined<T>(value?: T): value is NonNullable<T> {
*
* @internal
*/
export const isDefinedFrom = <T>(typeCheck: (value: RecursivePartial<T>) => boolean) => (
export const isDefinedFrom = <T,>(typeCheck: (value: RecursivePartial<T>) => boolean) => (
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Converting this from *.ts to *.tsx file, the generic const function declaration has issues.

This is a convenient fix that does not affect the type of the generic.

See https://stackoverflow.com/questions/32308370/what-is-the-syntax-for-typescript-arrow-functions-with-generics

Copy link
Member

Choose a reason for hiding this comment

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

What if instead of having this hack (as described in the stackoverflow comment) we transform these to named functions?

@nickofthyme nickofthyme marked this pull request as ready for review April 19, 2021 21:37
Comment on lines +23 to +27
import * as common from '../../../../../utils/common';
import { buildAreaStyles } from './area';

jest.mock('../../../../../common/color_library_wrappers');
jest.mock('../../../../../utils/common');
jest.spyOn(common, 'getColorFromVariant');
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I'm not sure how or why my changes to utils/common.ts(x) affected this but this caused mocks to return undefined. This changes the logic to now only spys on the common#getColorFromVariant utils module method for conducting mock returns in styles unit tests.

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.

LGTM. Tested locally and works fine.
I've few doubts about the "padding" comments on the story, but I think it's fine leaving it like that. Probably a different background for the annotation or pushing the annotation text and line after the axis labels can be useful

@@ -541,7 +558,7 @@ export function isDefined<T>(value?: T): value is NonNullable<T> {
*
* @internal
*/
export const isDefinedFrom = <T>(typeCheck: (value: RecursivePartial<T>) => boolean) => (
export const isDefinedFrom = <T,>(typeCheck: (value: RecursivePartial<T>) => boolean) => (
Copy link
Member

Choose a reason for hiding this comment

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

What if instead of having this hack (as described in the stackoverflow comment) we transform these to named functions?

src/chart_types/xy_chart/utils/specs.ts Outdated Show resolved Hide resolved
Comment on lines +75 to +77
const setPopper = useCallback(() => {
if (!iconRef.current || !testRef.current) return;

Copy link
Member

Choose a reason for hiding this comment

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

On a different PR we should extract the popper.js to be a HOF or something similar to enhance the positioning of everything that we need

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

That's not a bad idea. I wonder if the logic is too bespoke for a HOC, I could see a class. Anyway, happy to discuss this in the future. I also secretly want to test popper on eui and see if it's better performance 🤪, we'll see if I ever have the time.

@nickofthyme nickofthyme enabled auto-merge (squash) April 21, 2021 14:45
@nickofthyme nickofthyme changed the title feat(annotations): marker wrapping feat(annotations): marker body with dynamic positioning Apr 21, 2021
@nickofthyme nickofthyme merged commit 601abac into elastic:master Apr 22, 2021
nickofthyme pushed a commit that referenced this pull request Apr 22, 2021
# [29.0.0](v28.2.0...v29.0.0) (2021-04-22)

### Features

* **a11y:** add label for screen readers ([#1121](#1121)) ([920e585](920e585)), closes [#1096](#1096)
* **annotations:** marker body with dynamic positioning ([#1116](#1116)) ([601abac](601abac))

### BREAKING CHANGES

* **a11y:** `description` prop in `<Settings/>` is renamed to `ariaDescription`

Co-authored-by: Marco Vettorello <vettorello.marco@gmail.com>
@nickofthyme
Copy link
Collaborator Author

🎉 This PR is included in version 29.0.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

@nickofthyme nickofthyme added the released Issue released publicly label Apr 22, 2021
@nickofthyme nickofthyme deleted the fix-anno-marker-wrap branch September 18, 2021 20:20
AMoo-Miki pushed a commit to AMoo-Miki/OpenSearch-Dashboards that referenced this pull request Feb 10, 2022
# [29.0.0](elastic/elastic-charts@v28.2.0...v29.0.0) (2021-04-22)

### Features

* **a11y:** add label for screen readers ([opensearch-project#1121](elastic/elastic-charts#1121)) ([ddb8782](elastic/elastic-charts@ddb8782)), closes [opensearch-project#1096](elastic/elastic-charts#1096)
* **annotations:** marker body with dynamic positioning ([#1116](elastic/elastic-charts#1116)) ([997d487](elastic/elastic-charts@997d487))

### BREAKING CHANGES

* **a11y:** `description` prop in `<Settings/>` is renamed to `ariaDescription`

Co-authored-by: Marco Vettorello <vettorello.marco@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
:annotation Annotation (line, rect, text) related issue bug Something isn't working enhancement New feature or request released Issue released publicly
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Right annotation icon misaligned Re-position chart annotation when it is near the border
2 participants