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({ })} - +