[WEB-2316] chore: Render Tooltips and Drop downs in certain places on hover hover to improve rendering performance (#5456)

* render tooltips and dropdowns in certain places post hover to improve performance

* fix useEffect hooks
This commit is contained in:
rahulramesha 2024-08-29 21:07:49 +05:30 committed by GitHub
parent 33ab6029dc
commit 693085577d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 684 additions and 515 deletions

View file

@ -0,0 +1,73 @@
import { Combobox } from "@headlessui/react";
import React, {
ElementType,
Fragment,
KeyboardEventHandler,
ReactNode,
Ref,
forwardRef,
useEffect,
useRef,
useState,
} from "react";
type Props = {
as?: ElementType | undefined;
ref?: Ref<HTMLElement> | undefined;
tabIndex?: number | undefined;
className?: string | undefined;
value?: string | string[] | null;
onChange?: (value: any) => void;
disabled?: boolean | undefined;
onKeyDown?: KeyboardEventHandler<HTMLDivElement> | undefined;
multiple?: boolean;
renderByDefault?: boolean;
button: ReactNode;
children: ReactNode;
};
const ComboDropDown = forwardRef((props: Props, ref) => {
const { button, renderByDefault = true, children, ...rest } = props;
const dropDownButtonRef = useRef<HTMLDivElement | null>(null);
const [shouldRender, setShouldRender] = useState(renderByDefault);
const onHover = () => {
setShouldRender(true);
};
useEffect(() => {
const element = dropDownButtonRef.current;
if (!element) return;
element.addEventListener("mouseenter", onHover);
return () => {
element?.removeEventListener("mouseenter", onHover);
};
}, [dropDownButtonRef, shouldRender]);
if (!shouldRender) {
return (
<div ref={dropDownButtonRef} className="h-full flex items-center">
{button}
</div>
);
}
return (
//@ts-ignore
<Combobox {...rest} ref={ref}>
<Combobox.Button as={Fragment}>{button}</Combobox.Button>
{children}
</Combobox>
);
});
const ComboOptions = Combobox.Options;
const ComboOption = Combobox.Option;
const ComboInput = Combobox.Input;
export { ComboDropDown, ComboOptions, ComboOption, ComboInput };

View file

@ -2,3 +2,4 @@ export * from "./context-menu";
export * from "./custom-menu";
export * from "./custom-select";
export * from "./custom-search-select";
export * from "./combo-box";

View file

@ -1,4 +1,4 @@
import React from "react";
import React, { useEffect, useRef, useState } from "react";
import { Tooltip2 } from "@blueprintjs/popover2";
// helpers
import { cn } from "../../helpers";
@ -42,37 +42,67 @@ export const Tooltip: React.FC<ITooltipProps> = ({
openDelay = 200,
closeDelay,
isMobile = false,
}) => (
<Tooltip2
disabled={disabled}
hoverOpenDelay={openDelay}
hoverCloseDelay={closeDelay}
content={
<div
className={cn(
"relative block z-50 max-w-xs gap-1 overflow-hidden break-words rounded-md bg-custom-background-100 p-2 text-xs text-custom-text-200 shadow-md",
{
hidden: isMobile,
},
className
)}
>
{tooltipHeading && <h5 className="font-medium text-custom-text-100">{tooltipHeading}</h5>}
{tooltipContent}
}) => {
const toolTipRef = useRef<HTMLDivElement | null>(null);
const [shouldRender, setShouldRender] = useState(false);
const onHover = () => {
setShouldRender(true);
};
useEffect(() => {
const element = toolTipRef.current;
if (!element) return;
element.addEventListener("mouseenter", onHover);
return () => {
element?.removeEventListener("mouseenter", onHover);
};
}, [toolTipRef, shouldRender]);
if (!shouldRender) {
return (
<div ref={toolTipRef} className="h-full flex items-center">
{children}
</div>
}
position={position}
renderTarget={({
// eslint-disable-next-line @typescript-eslint/no-unused-vars
isOpen: isTooltipOpen,
ref: eleReference,
...tooltipProps
}) =>
React.cloneElement(children, {
);
}
return (
<Tooltip2
disabled={disabled}
hoverOpenDelay={openDelay}
hoverCloseDelay={closeDelay}
content={
<div
className={cn(
"relative block z-50 max-w-xs gap-1 overflow-hidden break-words rounded-md bg-custom-background-100 p-2 text-xs text-custom-text-200 shadow-md",
{
hidden: isMobile,
},
className
)}
>
{tooltipHeading && <h5 className="font-medium text-custom-text-100">{tooltipHeading}</h5>}
{tooltipContent}
</div>
}
position={position}
renderTarget={({
// eslint-disable-next-line @typescript-eslint/no-unused-vars
isOpen: isTooltipOpen,
ref: eleReference,
...tooltipProps,
...children.props,
})
}
/>
);
...tooltipProps
}) =>
React.cloneElement(children, {
ref: eleReference,
...tooltipProps,
...children.props,
})
}
/>
);
};