Skip to content

Commit

Permalink
Clean up tooltip positioning
Browse files Browse the repository at this point in the history
  • Loading branch information
susiekims committed Jan 24, 2024
1 parent 147087f commit 6e0d551
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 72 deletions.
1 change: 1 addition & 0 deletions .storybook/preview.js
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ const Container = ({children, theme}: ContainerProps) => {
overflow: 'hidden',
margin: '-1rem',
background: selectedTheme.chartContainer.backgroundColor,
padding: '1000px 0',
}}
>
<div
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ import {
useChartContext,
useTheme,
} from '@shopify/polaris-viz-core';
import type {Direction, Dimensions} from '@shopify/polaris-viz-core';
import type {
Direction,
Dimensions,
BoundingRect,
} from '@shopify/polaris-viz-core';

import {DEFAULT_LEGEND_HEIGHT, DEFAULT_LEGEND_WIDTH} from '../../constants';
import {useResizeObserver, useWatchColorVisionEvents} from '../../hooks';
Expand Down Expand Up @@ -42,6 +46,7 @@ export interface LegendContainerProps {
renderHiddenLegendLabel?: RenderHiddenLegendLabel;
/* If enabled, hides overflowing legend items with "+ n more" */
hideOverflow?: boolean;
chartBounds: BoundingRect;
}

export function LegendContainer({
Expand All @@ -56,6 +61,7 @@ export function LegendContainer({
width,
hideOverflow = false,
renderHiddenLegendLabel = (count) => `+${count} more`,
chartBounds,
}: LegendContainerProps) {
const selectedTheme = useTheme();
const {setRef, entry} = useResizeObserver();
Expand Down Expand Up @@ -192,6 +198,7 @@ export function LegendContainer({
)}
lastVisibleIndex={allData.length - hiddenData.length}
setButtonWidth={setButtonWidth}
chartBounds={chartBounds}
/>
)}
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,4 @@
border-radius: 5px;
box-shadow: 0 0 2px rgba(0, 0, 0, 0.2), 0 2px 10px rgba(0, 0, 0, 0.1);
position: absolute;
top: 0;
left: 0;
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {ReactNode, useEffect, useRef, useState} from 'react';
import {ReactNode, useCallback, useEffect, useRef, useState} from 'react';
import {Legend} from '../../Legend/Legend';
import type {LegendData} from '../../../types';

Expand Down Expand Up @@ -33,93 +33,81 @@ export function HiddenLegendPopover({
const {isFirefox} = useBrowserCheck();
useColorVisionEvents(true, {});
const container = useRootContainer('hidden-legend-tooltip');
const legendItemsRef = useRef<HTMLDivElement>(null);
const anchorRef = useRef<HTMLButtonElement>(null);
const tooltipRef = useRef<HTMLDivElement>(null);
const activatorRef = useRef<HTMLButtonElement>(null);

const [position, setPosition] = useState<string | null>(null);
const [position, setPosition] = useState<{top: number; left: number}>({
top: 0,
left: 0,
});
const [active, setActive] = useState(false);

useEffect(() => {
if (legendItemsRef.current == null || anchorRef.current == null) {
if (tooltipRef.current == null || activatorRef.current == null) {
return;
}

const {width: anchorWidth} = anchorRef.current.getBoundingClientRect();
const activator = activatorRef.current.getBoundingClientRect();
const tooltip = tooltipRef.current.getBoundingClientRect();

setButtonWidth(anchorWidth);
}, [legendItemsRef.current, anchorRef.current]);
const xPosition = activator.x + window.scrollX;
const yPosition = activator.y + window.scrollY + activator.height;

function getTooltipPosition() {
if (legendItemsRef.current == null || anchorRef.current == null) {
return;
}

const {
width: anchorWidth,
top,
bottom,
left,
right,
} = anchorRef.current.getBoundingClientRect();

console.log(anchorRef.current.offsetTop, anchorRef.current.scrollTop);

setButtonWidth(anchorWidth);
function getXPosition() {
const goesPastRightOfWindow =
xPosition + tooltip.width > window.innerWidth;

const {height: tooltipHeight, width: tooltipWidth} =
legendItemsRef.current.getBoundingClientRect();
if (goesPastRightOfWindow) {
return xPosition - tooltip.width + activator.width;
}
return xPosition;
}

const goesPastBottomOfWindow = bottom + tooltipHeight >= window.innerHeight;
const goesPastRightOfWindow = left + tooltipWidth > window.innerWidth;
function getYPosition() {
const goesPastBottomOfWindow =
yPosition + tooltip.height >= window.innerHeight;
if (goesPastBottomOfWindow) {
return yPosition - tooltip.height - activator.height;
}

if (goesPastBottomOfWindow && goesPastRightOfWindow) {
// top-left
setPosition(
`translate(${right - tooltipWidth}px, ${top - tooltipHeight}px)`,
);
} else if (goesPastBottomOfWindow && !goesPastRightOfWindow) {
// top-right
setPosition(`translate(${left}px, ${top - tooltipHeight}px)`);
} else if (!goesPastBottomOfWindow && goesPastRightOfWindow) {
// bottom-left
setPosition(`translate(${right - tooltipWidth}px, ${bottom}px)`);
} else {
// default: bottom-right
setPosition(`translate(${left}px, ${bottom}px)`);
return yPosition;
}
}

function handleMouseLeave(event) {
if (event.relatedTarget.id !== 'hidden-legend-items-tooltip') {
setPosition(null);
}
}
setPosition({
top: getYPosition(),
left: getXPosition(),
});

setButtonWidth(activator.width);
}, [tooltipRef.current, activatorRef.current]);

return (
<>
<button
className={style.MoreText}
ref={anchorRef}
onMouseEnter={getTooltipPosition}
onMouseLeave={handleMouseLeave}
ref={activatorRef}
onMouseOver={() => {
setActive(true);
}}
onMouseLeave={() => setActive(false)}
>
{label}
</button>

{createPortal(
<div
className={style.LegendItems}
ref={legendItemsRef}
ref={tooltipRef}
id="hidden-legend-items-tooltip"
style={{
visibility: position ? 'visible' : 'hidden',
zIndex: position ? 1 : -100000,
visibility: active ? 'visible' : 'hidden',
zIndex: active ? 1 : -100000,
background: changeColorOpacity(
selectedTheme.tooltip.backgroundColor,
isFirefox ? 1 : TOOLTIP_BG_OPACITY,
),

transform: position ?? undefined,
...position,
}}
onMouseLeave={() => setPosition(null)}
>
<Legend
activeIndex={activeIndex}
Expand All @@ -129,18 +117,6 @@ export function HiddenLegendPopover({
lastVisibleIndex={lastVisibleIndex}
backgroundColor="transparent"
/>
{/* {data.map((item, index) => {
return (
<TooltipRow
activeIndex={activeIndex}
index={index}
label={item.name}
color={item.color}
shape={item.shape || 'Line'}
value={''}
/>
);
})} */}
</div>,
container,
)}
Expand Down

0 comments on commit 6e0d551

Please sign in to comment.