Anchored tooltip (#15568)
Issue - - tooltip gets too long when groupby has too much data points - we need max height on tooltips - we need to be able to scroll inside the tooltip - not possible if the tooltip is following the cursor (which library enforces) - its not easy to customize Nivo's own tooltip to make it work how we want it what we want - - let the tooltip anchor to the bar in such a way -- that the top of the bar aligns with the vertical middle of the tooltip - add max height to the tooltip what I did - - use floating portal from floating-ui/react - get the hover datum (ie hovered bars) dimensions on mouse enter to render the tooltip - anchor the tooltip at the calculated position - floating-ui handles the basic things like flipping/offset/shift - clear the states as required --------- Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
This commit is contained in:
+15
@@ -0,0 +1,15 @@
|
||||
import { type VirtualElement } from '@floating-ui/react';
|
||||
|
||||
type ChartCoordinates = {
|
||||
left: number;
|
||||
top: number;
|
||||
};
|
||||
|
||||
export const createVirtualElementFromChartCoordinates = (
|
||||
chartCoordinates: ChartCoordinates,
|
||||
): VirtualElement => {
|
||||
const { left, top } = chartCoordinates;
|
||||
return {
|
||||
getBoundingClientRect: () => new DOMRect(left, top, 1, 1),
|
||||
};
|
||||
};
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
import { type VirtualElement } from '@floating-ui/react';
|
||||
|
||||
export const createVirtualElementFromContainerOffset = (
|
||||
container: Element,
|
||||
offsetLeft: number,
|
||||
offsetTop: number,
|
||||
): VirtualElement => {
|
||||
return {
|
||||
getBoundingClientRect: () => {
|
||||
const rect = container.getBoundingClientRect();
|
||||
const left = rect.left + offsetLeft;
|
||||
const top = rect.top + offsetTop;
|
||||
return new DOMRect(left, top, 1, 1);
|
||||
},
|
||||
};
|
||||
};
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
import { type VirtualElement } from '@floating-ui/react';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const createVirtualElementFromSVGElement = (
|
||||
svgElement: Element,
|
||||
): VirtualElement | null => {
|
||||
const svgContainer = svgElement.closest('svg');
|
||||
if (!isDefined(svgContainer)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
getBoundingClientRect: () => {
|
||||
const elementRect = svgElement.getBoundingClientRect();
|
||||
return new DOMRect(
|
||||
elementRect.left,
|
||||
elementRect.top,
|
||||
elementRect.width,
|
||||
1,
|
||||
);
|
||||
},
|
||||
};
|
||||
};
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
import { type VirtualElement } from '@floating-ui/react';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const getTooltipReferenceFromBarChartElementAnchor = (
|
||||
anchorElement: Element,
|
||||
containerId: string,
|
||||
): {
|
||||
reference: Element | VirtualElement;
|
||||
boundary: Element;
|
||||
} => {
|
||||
const containerElement = document.getElementById(containerId);
|
||||
|
||||
if (!isDefined(containerElement)) {
|
||||
throw new Error(`Bar chart container not found: ${containerId}`);
|
||||
}
|
||||
|
||||
return { reference: anchorElement, boundary: containerElement };
|
||||
};
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
import { createVirtualElementFromContainerOffset } from '@/page-layout/widgets/graph/utils/createVirtualElementFromContainerOffset';
|
||||
import { type VirtualElement } from '@floating-ui/react';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const getTooltipReferenceFromLineChartPointAnchor = (
|
||||
containerId: string,
|
||||
offsetLeft: number,
|
||||
offsetTop: number,
|
||||
): {
|
||||
reference: VirtualElement;
|
||||
boundary: Element;
|
||||
} => {
|
||||
const containerElement = document.getElementById(containerId);
|
||||
|
||||
if (!isDefined(containerElement)) {
|
||||
throw new Error(`Chart container not found: ${containerId}`);
|
||||
}
|
||||
|
||||
return {
|
||||
reference: createVirtualElementFromContainerOffset(
|
||||
containerElement,
|
||||
offsetLeft,
|
||||
offsetTop,
|
||||
),
|
||||
boundary: containerElement,
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user