diff --git a/packages/polaris-viz-core/src/utilities/getColorVisionEventAttrs.ts b/packages/polaris-viz-core/src/utilities/getColorVisionEventAttrs.ts
index 7713aa37a..5abc388b7 100644
--- a/packages/polaris-viz-core/src/utilities/getColorVisionEventAttrs.ts
+++ b/packages/polaris-viz-core/src/utilities/getColorVisionEventAttrs.ts
@@ -11,6 +11,6 @@ export function getColorVisionEventAttrs({type, index, watch = true}: Props) {
[`${COLOR_VISION_EVENT.dataAttribute}-watch`]: watch,
[`${COLOR_VISION_EVENT.dataAttribute}-type`]: type,
[`${COLOR_VISION_EVENT.dataAttribute}-index`]: index,
- ['data-tooltip-type']: 'blah',
+ // ['data-tooltip-type']: 'blah',
};
}
diff --git a/packages/polaris-viz/src/components/BarChart/stories/data.tsx b/packages/polaris-viz/src/components/BarChart/stories/data.tsx
index 3b87de5f7..7e577eb54 100644
--- a/packages/polaris-viz/src/components/BarChart/stories/data.tsx
+++ b/packages/polaris-viz/src/components/BarChart/stories/data.tsx
@@ -12,37 +12,37 @@ export const DEFAULT_DATA: DataSeries[] = [
{
name: 'Breakfast',
data: [
- {key: 'Monday', value: 3},
- {key: 'Tuesday', value: -7},
- {key: 'Wednesday', value: -7},
- {key: 'Thursday', value: -8},
- {key: 'Friday', value: 45},
- {key: 'Saturday', value: 0},
- {key: 'Sunday', value: 0.1},
+ {key: 'Monday', value: 20},
+ {key: 'Tuesday', value: 20},
+ {key: 'Wednesday', value: 20},
+ {key: 'Thursday', value: 20},
+ {key: 'Friday', value: 20},
+ {key: 'Saturday', value: 20},
+ {key: 'Sunday', value: 20},
],
},
{
name: 'Lunch',
data: [
- {key: 'Monday', value: 4},
- {key: 'Tuesday', value: 0},
- {key: 'Wednesday', value: -10},
- {key: 'Thursday', value: 15},
- {key: 'Friday', value: 8},
- {key: 'Saturday', value: 45},
- {key: 'Sunday', value: 0.1},
+ {key: 'Monday', value: 20},
+ {key: 'Tuesday', value: 20},
+ {key: 'Wednesday', value: 20},
+ {key: 'Thursday', value: 20},
+ {key: 'Friday', value: 20},
+ {key: 'Saturday', value: 20},
+ {key: 'Sunday', value: 20},
],
},
{
name: 'Dinner',
data: [
- {key: 'Monday', value: 7},
- {key: 'Tuesday', value: 0},
- {key: 'Wednesday', value: -15},
- {key: 'Thursday', value: -12},
- {key: 'Friday', value: 45},
- {key: 'Saturday', value: 5},
- {key: 'Sunday', value: 0.1},
+ {key: 'Monday', value: 20},
+ {key: 'Tuesday', value: 20},
+ {key: 'Wednesday', value: 20},
+ {key: 'Thursday', value: 20},
+ {key: 'Friday', value: 20},
+ {key: 'Saturday', value: 20},
+ {key: 'Sunday', value: 20},
],
},
];
diff --git a/packages/polaris-viz/src/components/ComboChart/Chart.tsx b/packages/polaris-viz/src/components/ComboChart/Chart.tsx
index eeb46c2df..d93da7393 100644
--- a/packages/polaris-viz/src/components/ComboChart/Chart.tsx
+++ b/packages/polaris-viz/src/components/ComboChart/Chart.tsx
@@ -23,7 +23,7 @@ import {
checkAvailableAnnotations,
YAxisAnnotations,
} from '../Annotations';
-import {TooltipWrapper} from '../TooltipWrapper';
+// import {TooltipWrapper} from '../TooltipWrapper';
import type {
AnnotationLookupTable,
RenderLegendContent,
@@ -317,7 +317,7 @@ export function Chart({
)}
-
+ /> */}
{showLegend && (
{
+ const x =
+ index * (drawableWidth / longestSeriesLength) -
+ drawableWidth / longestSeriesLength / 2;
+ const width = drawableWidth / longestSeriesLength;
+
return (
);
})}
diff --git a/packages/polaris-viz/src/components/TooltipWrapper/TooltipWrapperNext.tsx b/packages/polaris-viz/src/components/TooltipWrapper/TooltipWrapperNext.tsx
index ddef10f79..102019f21 100644
--- a/packages/polaris-viz/src/components/TooltipWrapper/TooltipWrapperNext.tsx
+++ b/packages/polaris-viz/src/components/TooltipWrapper/TooltipWrapperNext.tsx
@@ -1,7 +1,7 @@
import type {ReactNode} from 'react';
import {useEffect, useRef, useState, useMemo, useCallback} from 'react';
import {useChartContext, InternalChartType} from '@shopify/polaris-viz-core';
-import type {DataType} from '@shopify/polaris-viz-core';
+import type {BoundingRect} from '@shopify/polaris-viz-core';
import {createPortal} from 'react-dom';
import {useRootContainer} from '../../hooks/useRootContainer';
@@ -17,7 +17,6 @@ const TOUCH_START_DELAY = 300;
interface BaseProps {
chartType: InternalChartType;
- focusElementDataType: DataType;
getMarkup: (index: number | null) => ReactNode;
parentElement: SVGSVGElement | null;
onIndexChange?: (index: number | null) => void;
@@ -25,13 +24,13 @@ interface BaseProps {
}
function TooltipWrapperRaw(props: BaseProps) {
- const {chartType, focusElementDataType, id, onIndexChange, parentElement} =
- props;
+ const {chartType, id, onIndexChange, parentElement} = props;
const {isTouchDevice, containerBounds} = useChartContext();
const [position, setPosition] = useState({
x: containerBounds.x,
y: containerBounds.y,
activeIndex: -1,
+ unsafeArea: null,
});
const activeIndexRef = useRef(null);
@@ -39,10 +38,8 @@ function TooltipWrapperRaw(props: BaseProps) {
const isLongTouch = useRef(false);
const focusElements = useMemo | undefined>(() => {
- return parentElement?.querySelectorAll(
- `[data-type="${focusElementDataType}"][aria-hidden="false"]`,
- );
- }, [focusElementDataType, parentElement]);
+ return parentElement?.querySelectorAll(`[data-tooltip-type]`);
+ }, [parentElement]);
useEffect(() => {
activeIndexRef.current = position.activeIndex;
@@ -54,54 +51,45 @@ function TooltipWrapperRaw(props: BaseProps) {
const getPosition = useCallback(
(event: MouseEvent | TouchEvent) => {
- console.log('getPosition');
-
if (shouldBlockTooltipEvents(event)) {
return {
+ ...position,
activeIndex: -1,
};
}
if (event == null || event.target == null) {
- console.log('no event or target', event);
return position;
}
const target = event.target as HTMLElement;
- if (target.dataset.tooltipType == null) {
- console.log('no type', target);
- return {
- // x: 0,
- // y: 0,
- activeIndex: -1,
- };
+ if (target.dataset.tooltipIndex == null) {
+ return position;
}
- const activeIndex = target.dataset.tooltipIndex;
-
- let x = Number(target.dataset.tooltipX);
- let y = Number(target.dataset.tooltipY);
+ const {x, y, activeIndex, unsafeArea} = getDataFromElement(target);
if (alwaysUpdatePosition) {
const {x: eventX, y: eventY} = getXYFromEventType(event);
- x = eventX;
- y = eventY;
+ return {
+ ...position,
+ x: eventX,
+ y: eventY,
+ activeIndex,
+ };
}
if (y == null || x == null) {
- // console.log('no x or y', target);
return position;
}
- // console.log('x or y', {x, y, activeIndex});
-
return {
x,
y,
- activeIndex:
- activeIndex == null ? position.activeIndex : Number(activeIndex),
+ activeIndex: activeIndex == null ? position.activeIndex : activeIndex,
+ unsafeArea,
};
},
[alwaysUpdatePosition, position],
@@ -169,16 +157,28 @@ function TooltipWrapperRaw(props: BaseProps) {
const onFocus = useCallback(
(event: FocusEvent) => {
- // const target = event.currentTarget as SVGSVGElement;
- // if (!target) {
- // return;
- // }
- // const index = Number(target.dataset.index);
- // const newPosition = getPosition({, eveindexntType: 'focus'});
- // setPosition(newPosition);
- // onIndexChange?.(newPosition.activeIndex);
+ const target = event.currentTarget as SVGSVGElement;
+
+ if (target == null) {
+ return;
+ }
+
+ const activeIndex = target.dataset.tooltipIndex;
+
+ const x = Number(target.dataset.tooltipX);
+ const y = Number(target.dataset.tooltipY);
+
+ const newActiveIndex = activeIndex == null ? -1 : Number(activeIndex);
+
+ setPosition((prevState) => ({
+ ...prevState,
+ x,
+ y,
+ activeIndex: newActiveIndex,
+ }));
+ onIndexChange?.(newActiveIndex);
},
- [getPosition, onIndexChange],
+ [onIndexChange],
);
const onFocusIn = useCallback(() => {
@@ -205,8 +205,6 @@ function TooltipWrapperRaw(props: BaseProps) {
);
useEffect(() => {
- console.log('useEffect', parentElement);
-
if (!parentElement) {
return;
}
@@ -244,16 +242,13 @@ function TooltipWrapperRaw(props: BaseProps) {
};
}, [parentElement, onFocusIn]);
- // if (position.activeIndex == null || position.activeIndex < 0) {
- // return null;
- // }
-
return (
{props.getMarkup(position.activeIndex)}
@@ -275,3 +270,41 @@ function TooltipWithPortal(props: BaseProps) {
container,
);
}
+
+function getDataFromElement(element: HTMLElement) {
+ const x = Number(element.dataset.tooltipX);
+ const y = Number(element.dataset.tooltipY);
+
+ const unsafeArea = getUnsafeAreaFromElement(element);
+ const activeIndex = element.dataset.tooltipIndex;
+
+ return {
+ x,
+ y,
+ activeIndex: activeIndex == null ? -1 : Number(activeIndex),
+ unsafeArea,
+ };
+}
+
+function getUnsafeAreaFromElement(element: HTMLElement): BoundingRect | null {
+ if (element.dataset.tooltipUnsafeArea == null) {
+ return null;
+ }
+
+ const unsafeArea = JSON.parse(element.dataset.tooltipUnsafeArea);
+
+ if (isUnsafeAreaValid(unsafeArea)) {
+ return unsafeArea;
+ }
+
+ return null;
+}
+
+function isUnsafeAreaValid(unsafeArea: unknown): boolean {
+ return (
+ Object.prototype.hasOwnProperty.call(unsafeArea, 'x') &&
+ Object.prototype.hasOwnProperty.call(unsafeArea, 'y') &&
+ Object.prototype.hasOwnProperty.call(unsafeArea, 'height') &&
+ Object.prototype.hasOwnProperty.call(unsafeArea, 'width')
+ );
+}
diff --git a/packages/polaris-viz/src/components/TooltipWrapper/components/TooltipAnimatedContainer.tsx b/packages/polaris-viz/src/components/TooltipWrapper/components/TooltipAnimatedContainer.tsx
index 24fe4b227..bcf90eaa8 100644
--- a/packages/polaris-viz/src/components/TooltipWrapper/components/TooltipAnimatedContainer.tsx
+++ b/packages/polaris-viz/src/components/TooltipWrapper/components/TooltipAnimatedContainer.tsx
@@ -1,7 +1,15 @@
import type {ReactNode} from 'react';
import {useEffect, useRef, useState} from 'react';
-import type {Dimensions} from '@shopify/polaris-viz-core';
-import {InternalChartType, useChartContext} from '@shopify/polaris-viz-core';
+import type {
+ BoundingRect,
+ Dimensions,
+ Position,
+} from '@shopify/polaris-viz-core';
+import {
+ useChartContext,
+ InternalChartType,
+ clamp,
+} from '@shopify/polaris-viz-core';
import styles from './TooltipAnimatedContainer.scss';
@@ -11,11 +19,12 @@ export interface TooltipAnimatedContainerProps {
activePointIndex: number | null;
x: number;
y: number;
+ unsafeArea: BoundingRect | null;
id?: string;
}
export function TooltipAnimatedContainer(props: TooltipAnimatedContainerProps) {
- const {activePointIndex, chartType, children, id = ''} = props;
+ const {activePointIndex, chartType, children, id = '', unsafeArea} = props;
const {isPerformanceImpacted} = useChartContext();
@@ -49,9 +58,7 @@ export function TooltipAnimatedContainer(props: TooltipAnimatedContainerProps) {
left: 0,
opacity: 1,
transform: `translate3d(${Math.round(x)}px, ${Math.round(y)}px, 0px)`,
- transition: 'opacity 300ms ease, transform 150ms',
-
- // transition: immediate ? 'none' : 'opacity 300ms ease, transform 150ms',
+ transition: immediate ? 'none' : 'opacity 300ms ease, transform 150ms',
}}
ref={tooltipRef}
aria-hidden="true"
@@ -68,8 +75,6 @@ export function TooltipAnimatedContainer(props: TooltipAnimatedContainerProps) {
let newX = x;
let newY = y;
- console.log({chartType});
-
switch (chartType) {
case InternalChartType.Bar:
newY -= tooltipDimensions.height;
@@ -79,33 +84,96 @@ export function TooltipAnimatedContainer(props: TooltipAnimatedContainerProps) {
break;
}
- return keepTooltipInView({x: newX, y: newY});
+ return findOptimalPosition({x: newX, y: newY});
}
- function keepTooltipInView({x, y}: {x: number; y: number}) {
+ function findOptimalPosition({x, y}: Position): Position {
if (tooltipDimensions == null) {
return {x, y};
}
- let newX = x;
- let newY = y;
-
- if (x + tooltipDimensions.width > window.innerWidth) {
- newX = window.innerWidth - tooltipDimensions.width;
+ if (isPositionValid({x, y})) {
+ return {x, y};
}
- if (x < 0) {
- newX = 0;
+ // If there's an unsafe area, try to position the tooltip around it
+ if (unsafeArea != null) {
+ const positions: Position[] = [
+ // Top
+ {
+ x: unsafeArea.x + (unsafeArea.width - tooltipDimensions.width) / 2,
+ y: unsafeArea.y - tooltipDimensions.height,
+ },
+ // Right
+ {
+ x: unsafeArea.x + unsafeArea.width,
+ y: unsafeArea.y,
+ },
+ // Left
+ {
+ x: unsafeArea.x - tooltipDimensions.width,
+ y: unsafeArea.y,
+ },
+ // Bottom
+ {
+ x: unsafeArea.x + (unsafeArea.width - tooltipDimensions.width) / 2,
+ y: unsafeArea.y + unsafeArea.height,
+ },
+ ];
+
+ const validPosition = positions.find((pos) => isPositionValid(pos));
+
+ if (validPosition) {
+ return validPosition;
+ }
}
- if (y + tooltipDimensions.height > window.innerHeight) {
- newY = window.innerHeight - tooltipDimensions.height;
+ // If no valid position found, constrain to window bounds
+ return {
+ x: clamp({
+ amount: x,
+ min: 0,
+ max: window.innerWidth - tooltipDimensions.width,
+ }),
+ y: clamp({
+ amount: y,
+ min: 0,
+ max: window.innerHeight - tooltipDimensions.height,
+ }),
+ };
+ }
+
+ function isPositionValid({x, y}: Position): boolean {
+ if (tooltipDimensions == null) {
+ return true;
}
- if (y < 0) {
- newY = 0;
+ const tooltipBounds = {
+ top: y,
+ left: x,
+ bottom: y + tooltipDimensions.height,
+ right: x + tooltipDimensions.width,
+ };
+
+ // Check if within window bounds
+ const isWithinWindow =
+ x >= 0 &&
+ y >= 0 &&
+ tooltipBounds.right <= window.innerWidth &&
+ tooltipBounds.bottom <= window.innerHeight;
+
+ // If no safe area, just check window bounds
+ if (unsafeArea == null) {
+ return isWithinWindow;
}
- return {x: newX, y: newY};
+ // Check if overlapping with safe area
+ const isOverlappingSafeArea =
+ tooltipBounds.right > unsafeArea.x &&
+ tooltipBounds.left < unsafeArea.x + unsafeArea.width &&
+ tooltipBounds.bottom > unsafeArea.y &&
+ tooltipBounds.top < unsafeArea.y + unsafeArea.height;
+
+ return isWithinWindow && !isOverlappingSafeArea;
}
}
diff --git a/packages/polaris-viz/src/components/TooltipWrapper/constants.ts b/packages/polaris-viz/src/components/TooltipWrapper/constants.ts
index ba0c9cf64..1d5154b78 100644
--- a/packages/polaris-viz/src/components/TooltipWrapper/constants.ts
+++ b/packages/polaris-viz/src/components/TooltipWrapper/constants.ts
@@ -9,8 +9,8 @@ export const DEFAULT_TOOLTIP_POSITION = {
export const TOOLTIP_POSITION_DEFAULT_RETURN: TooltipPosition = {
x: 0,
y: 0,
- position: DEFAULT_TOOLTIP_POSITION,
activeIndex: null,
+ unsafeArea: null,
};
// The space between the cursor and the tooltip
diff --git a/packages/polaris-viz/src/components/TooltipWrapper/tests/utils.test.ts b/packages/polaris-viz/src/components/TooltipWrapper/tests/utils.test.ts
deleted file mode 100644
index 17f45fe62..000000000
--- a/packages/polaris-viz/src/components/TooltipWrapper/tests/utils.test.ts
+++ /dev/null
@@ -1,184 +0,0 @@
-import {
- getAbovePosition,
- getBelowPosition,
- getCenterPosition,
- getInlinePosition,
- getLeftPosition,
- getRightPosition,
- getVerticalCenterPosition,
-} from '../utilities';
-import type {AlteredPositionProps} from '../utilities';
-
-const MARGIN = {Top: 0, Left: 0, Right: 0, Bottom: 0};
-const BASE_PROPS: AlteredPositionProps = {
- chartBounds: {height: 100, width: 100, x: 0, y: 0},
- tooltipDimensions: {height: 20, width: 20},
- margin: MARGIN,
- bandwidth: 40,
- currentX: 0,
- currentY: 0,
- position: {
- horizontal: 0,
- vertical: 0,
- },
- isPerformanceImpacted: false,
-};
-
-let windowSpy;
-
-function mockWindow({scrollY = 0, innerHeight = 1000, innerWidth = 500}) {
- windowSpy.mockImplementation(() => ({
- scrollY,
- innerHeight,
- innerWidth,
- }));
-}
-
-describe('utilities', () => {
- beforeEach(() => {
- windowSpy = jest.spyOn(window, 'window', 'get');
- mockWindow({});
- });
-
- afterEach(() => {
- windowSpy.mockRestore();
- });
-
- describe('getInlinePosition()', () => {
- it('returns altered values', () => {
- expect(getInlinePosition(30, BASE_PROPS)).toStrictEqual({
- value: 30,
- wasOutsideBounds: false,
- });
-
- expect(getInlinePosition(1000, BASE_PROPS)).toStrictEqual({
- value: 80,
- wasOutsideBounds: true,
- });
- });
- });
-
- describe('getVerticalCenterPosition()', () => {
- it('returns altered values', () => {
- expect(
- getVerticalCenterPosition(0, {...BASE_PROPS, currentY: 0}),
- ).toStrictEqual({
- value: 0,
- wasOutsideBounds: true,
- });
-
- expect(
- getVerticalCenterPosition(40, {...BASE_PROPS, currentY: 40}),
- ).toStrictEqual({
- value: 30,
- wasOutsideBounds: false,
- });
- });
- });
-
- describe('getAbovePosition()', () => {
- it('returns altered values', () => {
- const currentY = 0;
- const scrollTop = 15;
-
- expect(
- getAbovePosition(0, {
- ...BASE_PROPS,
- currentY,
- scrollContainer: {scrollTop} as Element,
- }),
- ).toStrictEqual({
- value: currentY - scrollTop,
- wasOutsideBounds: true,
- });
-
- expect(getAbovePosition(50, {...BASE_PROPS, currentY: 50})).toStrictEqual(
- {
- value: 10,
- wasOutsideBounds: false,
- },
- );
- });
- });
-
- describe('getBelowPosition()', () => {
- it('returns altered values', () => {
- expect(getBelowPosition(0, BASE_PROPS)).toStrictEqual({
- value: 40,
- wasOutsideBounds: false,
- });
-
- expect(getBelowPosition(40, BASE_PROPS)).toStrictEqual({
- value: 80,
- wasOutsideBounds: false,
- });
-
- expect(getBelowPosition(1090, BASE_PROPS)).toStrictEqual({
- value: 1090,
- wasOutsideBounds: true,
- });
- });
- });
-
- describe('getLeftPosition()', () => {
- it('returns altered values', () => {
- expect(getLeftPosition(0, {...BASE_PROPS, currentX: 0})).toStrictEqual({
- value: 60,
- wasOutsideBounds: true,
- });
-
- expect(getLeftPosition(40, {...BASE_PROPS, currentX: 40})).toStrictEqual({
- value: 0,
- wasOutsideBounds: false,
- });
-
- expect(getLeftPosition(90, {...BASE_PROPS, currentX: 90})).toStrictEqual({
- value: 50,
- wasOutsideBounds: false,
- });
- });
- });
-
- describe('getRightPosition()', () => {
- it('returns altered values', () => {
- expect(getRightPosition(0, BASE_PROPS)).toStrictEqual({
- value: 60,
- wasOutsideBounds: false,
- });
-
- expect(getRightPosition(40, BASE_PROPS)).toStrictEqual({
- value: 100,
- wasOutsideBounds: false,
- });
-
- expect(getRightPosition(690, BASE_PROPS)).toStrictEqual({
- value: 650,
- wasOutsideBounds: true,
- });
- });
- });
-
- describe('getCenterPosition()', () => {
- it('returns altered values', () => {
- expect(getCenterPosition(-10, BASE_PROPS)).toStrictEqual({
- value: 0,
- wasOutsideBounds: false,
- });
-
- expect(getCenterPosition(0, BASE_PROPS)).toStrictEqual({
- value: 10,
- wasOutsideBounds: false,
- });
-
- expect(getCenterPosition(40, BASE_PROPS)).toStrictEqual({
- value: 50,
- wasOutsideBounds: false,
- });
-
- expect(getCenterPosition(690, BASE_PROPS)).toStrictEqual({
- value: 440,
- wasOutsideBounds: true,
- });
- });
- });
-});
diff --git a/packages/polaris-viz/src/components/TooltipWrapper/types.ts b/packages/polaris-viz/src/components/TooltipWrapper/types.ts
index 471556069..c0f3ce699 100644
--- a/packages/polaris-viz/src/components/TooltipWrapper/types.ts
+++ b/packages/polaris-viz/src/components/TooltipWrapper/types.ts
@@ -2,12 +2,9 @@ import type {
BoundingRect,
ChartType,
DataSeries,
- Dimensions,
} from '@shopify/polaris-viz-core';
import type {ScaleBand, ScaleLinear} from 'd3-scale';
-import type {Margin} from '../../types';
-
export enum TooltipHorizontalOffset {
Left,
Right,
@@ -21,16 +18,11 @@ export enum TooltipVerticalOffset {
Center,
}
-export interface TooltipPositionOffset {
- horizontal: TooltipHorizontalOffset;
- vertical: TooltipVerticalOffset;
-}
-
export interface TooltipPosition {
x: number;
y: number;
activeIndex: number | null;
- position?: TooltipPositionOffset;
+ unsafeArea: BoundingRect | null;
}
export interface TooltipPositionParams {
@@ -44,26 +36,3 @@ export interface TooltipPositionParams {
type?: ChartType;
yScale?: ScaleLinear;
}
-
-export interface AlteredPositionProps {
- bandwidth: number;
- chartBounds: BoundingRect;
- currentX: number;
- currentY: number;
- containerBounds: BoundingRect;
- isPerformanceImpacted: boolean;
- isTouchDevice: boolean;
- margin: Margin;
- position: TooltipPositionOffset;
- tooltipDimensions: Dimensions;
- scrollContainer?: Element | null;
-}
-
-export interface AlteredPositionReturn {
- x: number;
- y: number;
-}
-
-export type AlteredPosition = (
- props: AlteredPositionProps,
-) => AlteredPositionReturn;
diff --git a/packages/polaris-viz/src/components/TooltipWrapper/utilities.ts b/packages/polaris-viz/src/components/TooltipWrapper/utilities.ts
deleted file mode 100644
index eb7f26e56..000000000
--- a/packages/polaris-viz/src/components/TooltipWrapper/utilities.ts
+++ /dev/null
@@ -1,182 +0,0 @@
-import {TOOLTIP_MARGIN} from './constants';
-import type {AlteredPositionProps} from './types';
-
-interface IsOutsideBoundsData {
- current: number;
- direction: 'x' | 'y';
- alteredPosition: AlteredPositionProps;
-}
-
-function isOutsideBounds(data: IsOutsideBoundsData): boolean {
- const {current, direction, alteredPosition} = data;
-
- if (direction === 'x') {
- const isLeft = current < 0;
- const isRight =
- current + alteredPosition.tooltipDimensions.width > window.innerWidth;
-
- return isLeft || isRight;
- } else {
- const isAbove = current < window.scrollY;
- const isBelow =
- current + alteredPosition.tooltipDimensions.height >
- window.scrollY +
- window.innerHeight -
- alteredPosition.tooltipDimensions.height;
-
- return isAbove || isBelow;
- }
-}
-
-type getFunction = (
- value: number,
- props: AlteredPositionProps,
-) => {value: number; wasOutsideBounds: boolean};
-
-export function getInlinePosition(
- ...args: Parameters
-): ReturnType {
- const [value, props] = args;
-
- let y = value;
- const wasOutsideBounds = isOutsideBounds({
- current: y,
- direction: 'y',
- alteredPosition: props,
- });
-
- if (wasOutsideBounds) {
- const bottom = y + props.tooltipDimensions.height;
- const offset = bottom - props.chartBounds.height;
-
- y -= offset + props.margin.Bottom;
- }
-
- return {value: y, wasOutsideBounds};
-}
-
-export function getVerticalCenterPosition(
- ...args: Parameters
-): ReturnType {
- const [value, props] = args;
-
- let y = value - props.tooltipDimensions.height / 2;
- const wasOutsideBounds = isOutsideBounds({
- current: y,
- direction: 'y',
- alteredPosition: props,
- });
-
- if (wasOutsideBounds) {
- if (y <= 0) {
- y = 0;
- } else {
- y = window.scrollY + window.innerHeight - props.tooltipDimensions.height;
- }
- }
-
- return {value: y, wasOutsideBounds};
-}
-
-export function getAbovePosition(
- ...args: Parameters
-): ReturnType {
- const [value, props] = args;
-
- let y = value - props.tooltipDimensions.height - TOOLTIP_MARGIN;
- const wasOutsideBounds = isOutsideBounds({
- current: y,
- direction: 'y',
- alteredPosition: props,
- });
- if (wasOutsideBounds) {
- y = props.currentY - (props.scrollContainer?.scrollTop ?? 0);
- }
-
- return {value: y, wasOutsideBounds};
-}
-
-export function getBelowPosition(
- ...args: Parameters
-): ReturnType {
- const [value, props] = args;
-
- let y = value + TOOLTIP_MARGIN * 2;
- const wasOutsideBounds = isOutsideBounds({
- current: y,
- direction: 'y',
- alteredPosition: props,
- });
-
- if (wasOutsideBounds) {
- y -= props.tooltipDimensions.height + TOOLTIP_MARGIN;
- }
-
- return {value: y, wasOutsideBounds};
-}
-
-export function getLeftPosition(
- ...args: Parameters
-): ReturnType {
- const [value, props] = args;
-
- let x = value - props.tooltipDimensions.width;
- const wasOutsideBounds = isOutsideBounds({
- current: x,
- direction: 'x',
- alteredPosition: props,
- });
- if (wasOutsideBounds) {
- x = props.currentX + props.margin.Left + props.bandwidth + TOOLTIP_MARGIN;
- } else {
- x -= TOOLTIP_MARGIN;
- }
-
- return {value: x, wasOutsideBounds};
-}
-
-export function getRightPosition(
- ...args: Parameters
-): ReturnType {
- const [value, props] = args;
-
- let x = value + props.bandwidth;
- const wasOutsideBounds = isOutsideBounds({
- current: x,
- direction: 'x',
- alteredPosition: props,
- });
-
- if (wasOutsideBounds) {
- x -= props.tooltipDimensions.width + props.bandwidth + TOOLTIP_MARGIN;
- } else {
- x += TOOLTIP_MARGIN;
- }
-
- return {value: x, wasOutsideBounds};
-}
-
-export function getCenterPosition(
- ...args: Parameters
-): ReturnType {
- const [value, props] = args;
-
- const offset = props.bandwidth - props.tooltipDimensions.width;
- let x = value + offset / 2;
-
- if (x < props.margin.Left) {
- x = props.currentX + props.margin.Left;
- }
-
- const wasOutsideBounds = isOutsideBounds({
- current: x,
- direction: 'x',
- alteredPosition: props,
- });
-
- if (wasOutsideBounds) {
- x = window.innerWidth - props.tooltipDimensions.width - TOOLTIP_MARGIN * 2;
- }
-
- return {value: x, wasOutsideBounds};
-}
diff --git a/packages/polaris-viz/src/components/VerticalBarChart/components/BarGroup/BarGroup.tsx b/packages/polaris-viz/src/components/VerticalBarChart/components/BarGroup/BarGroup.tsx
index 5a19e443b..5c96fecb2 100644
--- a/packages/polaris-viz/src/components/VerticalBarChart/components/BarGroup/BarGroup.tsx
+++ b/packages/polaris-viz/src/components/VerticalBarChart/components/BarGroup/BarGroup.tsx
@@ -195,24 +195,27 @@ export function BarGroup({
})}
-
+