Skip to content

Commit

Permalink
feat(tooltip): add stickTo option (opensearch-project#1122)
Browse files Browse the repository at this point in the history
  • Loading branch information
markov00 committed Apr 23, 2021
1 parent 729c179 commit 534f2a3
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 10 deletions.
1 change: 1 addition & 0 deletions packages/osd-charts/api/charts.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -2018,6 +2018,7 @@ export type TooltipProps = TooltipPortalSettings<'chart'> & {
headerFormatter?: TooltipValueFormatter;
unit?: string;
customTooltip?: CustomTooltip;
stickTo?: Position;
};

// @public
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ import { TooltipAnchorPosition } from '../../../components/tooltip/types';
import { Line, Rect } from '../../../geoms/types';
import { Scale } from '../../../scales';
import { isContinuousScale } from '../../../scales/types';
import { Rotation } from '../../../utils/common';
import { TooltipProps } from '../../../specs/settings';
import { Position, Rotation } from '../../../utils/common';
import { Dimensions } from '../../../utils/dimensions';
import { Point } from '../../../utils/point';
import { isHorizontalRotation, isVerticalRotation } from '../state/utils/common';
Expand Down Expand Up @@ -177,10 +178,25 @@ export function getTooltipAnchorPosition(
cursorBandPosition: Line | Rect,
cursorPosition: { x: number; y: number },
panel: Dimensions,
stickTo?: TooltipProps['stickTo'],
): TooltipAnchorPosition {
const isRotated = isVerticalRotation(chartRotation);
const hPosition = getHorizontalTooltipPosition(cursorPosition.x, cursorBandPosition, panel, offset.left, isRotated);
const vPosition = getVerticalTooltipPosition(cursorPosition.y, cursorBandPosition, panel, offset.top, isRotated);
const hPosition = getHorizontalTooltipPosition(
cursorPosition.x,
cursorBandPosition,
panel,
offset.left,
isRotated,
stickTo,
);
const vPosition = getVerticalTooltipPosition(
cursorPosition.y,
cursorBandPosition,
panel,
offset.top,
isRotated,
stickTo,
);
return {
isRotated,
...vPosition,
Expand All @@ -194,6 +210,7 @@ function getHorizontalTooltipPosition(
panel: Dimensions,
globalOffset: number,
isRotated: boolean,
stickTo?: TooltipProps['stickTo'],
): { x0?: number; x1: number } {
if (!isRotated) {
const left = 'x1' in cursorBandPosition ? cursorBandPosition.x1 : cursorBandPosition.x;
Expand All @@ -203,10 +220,11 @@ function getHorizontalTooltipPosition(
x1: left + width + globalOffset,
};
}
const x = stickTo === Position.Left ? 0 : stickTo === Position.Right ? panel.width : cursorXPosition;
return {
// NOTE: x0 set to zero blocks tooltip placement on left when rotated 90 deg
// Delete this comment before merging and verifying this doesn't break anything.
x1: panel.left + cursorXPosition + globalOffset,
x1: panel.left + x + globalOffset,
};
}

Expand All @@ -216,15 +234,17 @@ function getVerticalTooltipPosition(
panel: Dimensions,
globalOffset: number,
isRotated: boolean,
stickTo?: TooltipProps['stickTo'],
): {
y0: number;
y1: number;
} {
const y = stickTo === Position.Top ? 0 : stickTo === Position.Bottom ? panel.height : cursorYPosition;
if (!isRotated) {
const y = cursorYPosition + panel.top + globalOffset;
const yPos = y + panel.top + globalOffset;
return {
y0: y,
y1: y,
y0: yPos,
y1: yPos,
};
}
const top = 'y1' in cursorBandPosition ? cursorBandPosition.y1 : cursorBandPosition.y;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import createCachedSelector from 're-reselect';

import { TooltipAnchorPosition } from '../../../../components/tooltip/types';
import { isTooltipType } from '../../../../specs/settings';
import { getChartIdSelector } from '../../../../state/selectors/get_chart_id';
import { getSettingsSpecSelector } from '../../../../state/selectors/get_settings_specs';
import { getTooltipAnchorPosition } from '../../crosshair/crosshair_utils';
Expand Down Expand Up @@ -64,6 +65,7 @@ export const getTooltipAnchorPositionSelector = createCachedSelector(
cursorBandPosition,
projectedPointerPosition,
panel,
isTooltipType(settings.tooltip) ? undefined : settings.tooltip.stickTo,
);
},
)(getChartIdSelector);
2 changes: 1 addition & 1 deletion packages/osd-charts/src/components/portal/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ export interface TooltipPortalSettings<B = never> {
boundary?: HTMLElement | B;
/**
* Boundary element padding.
* Used to reduce extents of boundary placement when magins or paddings are used on boundary
* Used to reduce extents of boundary placement when margins or paddings are used on boundary
*
* @defaultValue 0
*/
Expand Down
4 changes: 4 additions & 0 deletions packages/osd-charts/src/specs/settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,10 @@ export type TooltipProps = TooltipPortalSettings<'chart'> & {
* Render custom tooltip given header and values
*/
customTooltip?: CustomTooltip;
/**
* Stick the tooltip to a specific position within the current cursor
*/
stickTo?: Position;
};

/**
Expand Down
15 changes: 13 additions & 2 deletions packages/osd-charts/stories/area/2_with_time.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,28 @@
* under the License.
*/

import { number } from '@storybook/addon-knobs';
import React from 'react';

import { AreaSeries, Axis, Chart, Position, ScaleType, timeFormatter } from '../../src';
import { AreaSeries, Axis, Chart, Placement, Position, ScaleType, Settings, timeFormatter } from '../../src';
import { isDefined } from '../../src/utils/common';
import { KIBANA_METRICS } from '../../src/utils/data_samples/test_dataset_kibana';
import { getPlacementKnob, getPositionKnob } from '../utils/knobs';
import { SB_SOURCE_PANEL } from '../utils/storybook';

const dateFormatter = timeFormatter('HH:mm');

export const Example = () => (
<Chart className="story-chart">
<Settings
tooltip={{
stickTo: getPositionKnob('stickTo', Position.Top),
placement: getPlacementKnob('placement', Placement.RightEnd),
fallbackPlacements: [getPlacementKnob('fallback placement', Placement.LeftStart)].filter(isDefined),
offset: number('placement offset', 5),
}}
rotation={0}
/>
<Axis
id="bottom"
title="timestamp per 1 minute"
Expand All @@ -40,7 +52,6 @@ export const Example = () => (
position={Position.Left}
tickFormat={(d) => Number(d).toFixed(2)}
/>

<AreaSeries
id="area"
xScaleType={ScaleType.Time}
Expand Down

0 comments on commit 534f2a3

Please sign in to comment.